<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>python &amp;mdash; Блог Евгения Морозова</title>
    <link>https://emorozov.net/tag:python</link>
    <description></description>
    <pubDate>Wed, 03 Jun 2026 20:50:22 +0300</pubDate>
    <item>
      <title>Как организовать отдачу статических файлов в контейнеризованном Django</title>
      <link>https://emorozov.net/kak-organizovat-otdachu-staticheskikh-failov-v-konteinerizovannom-django</link>
      <description>&lt;![CDATA[Написал перед отпуском статью о часто возникающей проблеме при контейнеризациии приложений со статикой:&#xA;&#xA;Как организовать отдачу статических файлов в контейнеризованном Django&#xA;&#xA;Написано на примере Django, но сам принцип довольно общий и подойдёт для многих других фреймворков, языков и технологий.&#xA;&#xA;У меня нет действующего аккаунта на Хабре, поэтому опубликовано от имени Яндекс.Практикума.&#xA;&#xA;#django #python #docker]]&gt;</description>
      <content:encoded><![CDATA[<p>Написал перед отпуском статью о часто возникающей проблеме при контейнеризациии приложений со статикой:</p>

<p><a href="https://habr.com/ru/companies/yandex_praktikum/articles/755470/" rel="nofollow">Как организовать отдачу статических файлов в контейнеризованном Django</a></p>

<p>Написано на примере Django, но сам принцип довольно общий и подойдёт для многих других фреймворков, языков и технологий.</p>

<p>У меня нет действующего аккаунта на Хабре, поэтому опубликовано от имени Яндекс.Практикума.</p>

<p>#django #python #docker</p>
]]></content:encoded>
      <guid>https://emorozov.net/kak-organizovat-otdachu-staticheskikh-failov-v-konteinerizovannom-django</guid>
      <pubDate>Mon, 04 Sep 2023 11:50:44 +0000</pubDate>
    </item>
    <item>
      <title>Исправление ошибки в meliae</title>
      <link>https://emorozov.net/ispravlenie-oshibki-v-meliae</link>
      <description>&lt;![CDATA[Для поиска утечек памяти в приложениях на Python существует масса различных модулей, в том числе, уже встроенный в Python 3 модуль tracemalloc. Недостаток всех этих инструментов в том, что утечку надо воспроизвести в локальном окружении, а потом уже, используя pdb или ipdb, ковыряться в куче (heap), в поисках утекших объектов. Однако если у нас есть огромный проект, посещаемый миллионами пользователей, то воспроизвести утечку может оказаться невозможно, так как к ней приводит какое-то сочетание взаимодействия пользователей с проектом, которое не воспроизвести наугад.&#xA;&#xA;К счастью, нашёл проект meliae, позволяющий сделать дамп кучи в произвольный момент, с тем, чтобы проанализировать ее в оффлайне, уже не на боевом сервере.&#xA;&#xA;Однако, в проекте оказался досадный баг: целые числа Python он пытается сериализовать как тип C long. Но в Python целое число может быть произвольной разрядности, а в C long имеет разрядность 32 или 64 бит. Где-то в нашем проекте (или одной из его зависимостей) используются большие числа, поэтому создать дамп не удавалось, потому что этот процесс очень быстро обрывался с ошибкой OverflowError.&#xA;&#xA;Делать нечего, все другие варианты поиска утечки я уже попробовал без малейшего успеха. Скомпилировал Python из исходников с отладочной информацией, скомпилировал meliae, и стал вспоминать полузабытые навыки программирования на C и использования отладчика gdb. Довольно быстро нашел место возникновения ошибки, проблема была только в том, что времени на поиски у меня немного, а изучение того, как сдампить из модуля на C полноценное представление целого числа Python, потребовало бы длительного изучения устройства интерпретатора Python.&#xA;&#xA;В итоге воспользовался быстро найденной функцией PyLong_AsLongLongAndOverflow, которая возвращает -1, в случае, если число Python не помещается в long long. Сомневаюсь, что в нашем приложении утекают long, поэтому точное их значение меня не интересует.&#xA;&#xA;Свои правки положил здесь: https://github.com/emorozov/meliae&#xA;&#xA;Если удастся найти утечку памяти, постараюсь написать об этом тоже.&#xA;&#xA;#python #разработка]]&gt;</description>
      <content:encoded><![CDATA[<p>Для поиска утечек памяти в приложениях на Python существует масса различных модулей, в том числе, уже встроенный в Python 3 модуль <a href="https://docs.python.org/3/library/tracemalloc.html" rel="nofollow">tracemalloc</a>. Недостаток всех этих инструментов в том, что утечку надо воспроизвести в локальном окружении, а потом уже, используя pdb или ipdb, ковыряться в куче (heap), в поисках утекших объектов. Однако если у нас есть огромный проект, посещаемый миллионами пользователей, то воспроизвести утечку может оказаться невозможно, так как к ней приводит какое-то сочетание взаимодействия пользователей с проектом, которое не воспроизвести наугад.</p>

<p>К счастью, нашёл проект <a href="https://launchpad.net/meliae" rel="nofollow">meliae</a>, позволяющий сделать дамп кучи в произвольный момент, с тем, чтобы проанализировать ее в оффлайне, уже не на боевом сервере.</p>

<p>Однако, в проекте оказался досадный баг: целые числа Python он пытается сериализовать как тип C long. Но в Python целое число может быть произвольной разрядности, а в C long имеет разрядность 32 или 64 бит. Где-то в нашем проекте (или одной из его зависимостей) используются большие числа, поэтому создать дамп не удавалось, потому что этот процесс очень быстро обрывался с ошибкой <code>OverflowError</code>.</p>

<p>Делать нечего, все другие варианты поиска утечки я уже попробовал без малейшего успеха. Скомпилировал Python из исходников с отладочной информацией, скомпилировал meliae, и стал вспоминать полузабытые навыки программирования на C и использования отладчика gdb. Довольно быстро нашел место возникновения ошибки, проблема была только в том, что времени на поиски у меня немного, а изучение того, как сдампить из модуля на C полноценное представление целого числа Python, потребовало бы длительного изучения устройства интерпретатора Python.</p>

<p>В итоге воспользовался быстро найденной функцией <code>PyLong_AsLongLongAndOverflow</code>, которая возвращает -1, в случае, если число Python не помещается в <code>long long</code>. Сомневаюсь, что в нашем приложении утекают long, поэтому точное их значение меня не интересует.</p>

<p>Свои правки положил здесь: <a href="https://github.com/emorozov/meliae" rel="nofollow">https://github.com/emorozov/meliae</a></p>

<p>Если удастся найти утечку памяти, постараюсь написать об этом тоже.</p>

<p>#python #разработка</p>
]]></content:encoded>
      <guid>https://emorozov.net/ispravlenie-oshibki-v-meliae</guid>
      <pubDate>Sun, 17 May 2020 11:13:05 +0000</pubDate>
    </item>
    <item>
      <title>Вывод списка сигналов для всех моделей в проекте на Django</title>
      <link>https://emorozov.net/vyvod-spiska-signalov-dlia-vsekh-modelei-v-proekte-na-django</link>
      <description>&lt;![CDATA[В больших и старых проектах на Django бывает непросто найти ошибки из-за большого количества сигналов. Сигналы затрудняют анализ кода, так как обработчик может быть создан в любом модуле проекта, например, не в том, где определена модель, и вызывается неявно.&#xA;&#xA;Для облегчения поиска обработчиков нашел когда-то команду для Django, выводящую список всех обработчиков в проекте. Но она выводила только список обработчиков, без указания к какой модели они относятся. Чуть позже нашлась усовершенствованная версия, а затем я тоже приложил руки в процессе создания pull request для проекта django-extensions. Пришлось попотеть, так как django-extensions должен работать на большом количестве различных версий Python и Django (включая, например, PyPy). Но все препятствия удалось преодолеть, надеюсь, что мой код окажется в django-extensions, а пока оставляю ссылку на сам код команды, чтобы можно было пользоваться, пока рассматривается pull request:&#xA;list_signals.py&#xA;&#xA;#python #разработка]]&gt;</description>
      <content:encoded><![CDATA[<p>В больших и старых проектах на Django бывает непросто найти ошибки из-за большого количества сигналов. Сигналы затрудняют анализ кода, так как обработчик может быть создан в любом модуле проекта, например, не в том, где определена модель, и вызывается неявно.</p>

<p>Для облегчения поиска обработчиков нашел когда-то команду для Django, выводящую список всех обработчиков в проекте. Но она выводила только список обработчиков, без указания к какой модели они относятся. Чуть позже нашлась усовершенствованная версия, а затем я тоже приложил руки в процессе создания pull request для проекта <a href="https://github.com/django-extensions/django-extensions" rel="nofollow">django-extensions</a>. Пришлось попотеть, так как django-extensions должен работать на большом количестве различных версий Python и Django (включая, например, PyPy). Но все препятствия удалось преодолеть, надеюсь, что мой код окажется в django-extensions, а пока оставляю ссылку на сам код команды, чтобы можно было пользоваться, пока рассматривается pull request:
<a href="https://gist.github.com/emorozov/15bfca496a765d927dab627a6016ca58" rel="nofollow">list_signals.py</a></p>

<p>#python #разработка</p>
]]></content:encoded>
      <guid>https://emorozov.net/vyvod-spiska-signalov-dlia-vsekh-modelei-v-proekte-na-django</guid>
      <pubDate>Sun, 10 May 2020 07:57:28 +0000</pubDate>
    </item>
    <item>
      <title>PyCon Russia 2019</title>
      <link>https://emorozov.net/pycon-russia-2019</link>
      <description>&lt;![CDATA[Закончился PyCon. Кратко опишу свои впечатления. Было интересно, на некоторых докладах чувстовал, что делаю велосипеды, тогда как многие другие — космические корабли.&#xA;&#xA;Попытался участвовать в трех конкурсах:&#xA;Был смешной автоматик от Positive Technologies с вопросами по Python, некоторые весьма непростые. Выиграл мячик.&#xA;Была викторина в стиле «Что? Где? Когда?» от Яндекса, в которой играли командами. Наша команда заняла 8-е место из 12 (но мы были самой маленькой командой, поэтому нам пришлось вчетвером думать за десятерых).&#xA;Попытался поучаствовать в конкурсе от Positive Technologies, в котором надо было исправить несколько уязвимостей в Python приложениях.&#xA;&#xA;На первый взгляд, конкурс от PT был простой, но первый час я бился с тем, что мои решения не проходили, подошел к Ивану Цыганову, он выяснил, что на сервере проверки решений закончилось место. Затем хотелось прослушать почти все доклады, так что урывками пытался в перерывах копаться в коде, но все уязвимости исправить так и не успел. Тем более, мне показалось, что две исправленные уязвимости проверяльщик упорно не хотел засчитать.&#xA;&#xA;Но так как несколько человек этот этап прошли, то не уверен, проблема с моими исправлениями или проверяльщик все же ожидал какой-то шаблон, под который не подошло мое исправление. Иван обещал выложить исходники проверяльщика на GitHub, возможно, позже проверю.&#xA;&#xA;Из понравившихся докладов запомнились больше всего: доклад Ивана Цыганова об уязвимостях, доклад Златы Обуховской о проблемах с асинхронностью в Python, доклад Александра Кошелева о сборке образов Docker без build зависимостей (не rocket science, но очень жизненно), доклад Артёма Малышева о DDD, доклад Бориса Цема об уменьшении сложности проектов Wargaming. И доклад Бобука до кучи, потому что он вызвал самое бурное обсуждение и массу шуток.&#xA;&#xA;Все доклады прослушать не удалось. Часть докладов шла параллельно в двух разных залах, на части докладов пытался добить конкурс от PT, потому все пропустил мимо ушей.&#xA;&#xA;Лично мои ощущения. После более, чем 10 лет работы в удаленном режиме, мне завидно смотреть на ребят, которые приезжают вместе, общаются, обсуждают происходящее. Я этого всего лишен, и начинаю понимать, как этого не хватает. Поскольку по одиночке никто не приехал, кроме меня, втесаться в чью-то компанию очень сложно, мне это не удалось, к сожалению. Люди приехали из одной компании, давно друг-друга знают, у них свои шуточки о своих рабочих проблемах, и так далее. Вклиниться в такой разговор очень непросто, моих социальных навыков для этого, увы, не хватило.&#xA;&#xA;С другой стороны, скучать было некогда, пообщаться все же удалось, хотя не настолько плотно, как хотелось. Место было выбрано хорошее, в сосновом лесу. Организовано на уровне, любые организационные вопросы решались моментально, если вообще были.&#xA;&#xA;По итогам начал думать, что во-первых, хочу в офис. Мне надоела жизнь перекати поля и надоел вакуум вокруг, минимум общения, в том числе, общения на профессиональные темы.&#xA;&#xA;#pycon #python #работа]]&gt;</description>
      <content:encoded><![CDATA[<p>Закончился PyCon. Кратко опишу свои впечатления. Было интересно, на некоторых докладах чувстовал, что делаю велосипеды, тогда как многие другие — космические корабли.</p>

<p>Попытался участвовать в трех конкурсах:
1. Был смешной автоматик от Positive Technologies с вопросами по Python, некоторые весьма непростые. Выиграл мячик.
2. Была викторина в стиле «Что? Где? Когда?» от Яндекса, в которой играли командами. Наша команда заняла 8-е место из 12 (но мы были самой маленькой командой, поэтому нам пришлось вчетвером думать за десятерых).
3. Попытался поучаствовать в конкурсе от Positive Technologies, в котором надо было исправить несколько уязвимостей в Python приложениях.</p>

<p>На первый взгляд, конкурс от PT был простой, но первый час я бился с тем, что мои решения не проходили, подошел к Ивану Цыганову, он выяснил, что на сервере проверки решений закончилось место. Затем хотелось прослушать почти все доклады, так что урывками пытался в перерывах копаться в коде, но все уязвимости исправить так и не успел. Тем более, мне показалось, что две исправленные уязвимости проверяльщик упорно не хотел засчитать.</p>

<p>Но так как несколько человек этот этап прошли, то не уверен, проблема с моими исправлениями или проверяльщик все же ожидал какой-то шаблон, под который не подошло мое исправление. Иван обещал выложить исходники проверяльщика на GitHub, возможно, позже проверю.</p>

<p>Из понравившихся докладов запомнились больше всего: доклад Ивана Цыганова об уязвимостях, доклад Златы Обуховской о проблемах с асинхронностью в Python, доклад Александра Кошелева о сборке образов Docker без build зависимостей (не rocket science, но очень жизненно), доклад Артёма Малышева о DDD, доклад Бориса Цема об уменьшении сложности проектов Wargaming. И доклад Бобука до кучи, потому что он вызвал самое бурное обсуждение и массу шуток.</p>

<p>Все доклады прослушать не удалось. Часть докладов шла параллельно в двух разных залах, на части докладов пытался добить конкурс от PT, потому все пропустил мимо ушей.</p>

<p>Лично мои ощущения. После более, чем 10 лет работы в удаленном режиме, мне завидно смотреть на ребят, которые приезжают вместе, общаются, обсуждают происходящее. Я этого всего лишен, и начинаю понимать, как этого не хватает. Поскольку по одиночке никто не приехал, кроме меня, втесаться в чью-то компанию очень сложно, мне это не удалось, к сожалению. Люди приехали из одной компании, давно друг-друга знают, у них свои шуточки о своих рабочих проблемах, и так далее. Вклиниться в такой разговор очень непросто, моих социальных навыков для этого, увы, не хватило.</p>

<p>С другой стороны, скучать было некогда, пообщаться все же удалось, хотя не настолько плотно, как хотелось. Место было выбрано хорошее, в сосновом лесу. Организовано на уровне, любые организационные вопросы решались моментально, если вообще были.</p>

<p>По итогам начал думать, что во-первых, хочу в офис. Мне надоела жизнь перекати поля и надоел вакуум вокруг, минимум общения, в том числе, общения на профессиональные темы.</p>

<p>#pycon #python #работа</p>
]]></content:encoded>
      <guid>https://emorozov.net/pycon-russia-2019</guid>
      <pubDate>Wed, 26 Jun 2019 11:37:21 +0000</pubDate>
    </item>
    <item>
      <title>Решение ошибки Django OSError: No translation files found</title>
      <link>https://emorozov.net/reshenie-oshibki-django-oserror-no-translation-files-found-for-default-language</link>
      <description>&lt;![CDATA[Если вы разрабатываете сайт на языке не поддерживаемом Django, то можете столкнуться с подобной ошибкой:&#xA;  File &#34;/home/user/.virtualenvs/laos/lib/python3.7/site-packages/django/utils/translation/transreal.py&#34;, line 102, in init&#xA;    raise IOError(&#34;No translation files found for default language %s.&#34; % settings.LANGUAGECODE)&#xA;OSError: No translation files found for default language lo.&#xA;&#xA;Язык в settings.py определён правильно, ошибка довольно загадочная, и поиск не даёт разумных результатов.&#xA;&#xA;Если попытаться скомпилировать переводы командой compilemessages, то она естественно не выполняется с той же самой ошибкой.&#xA;&#xA;Самый простой способ обхода: перейти в каталог с переводами для данного языка и скомпилировать переводы вручную:&#xA;cd locale/lo/LC_MESSAGES&#xA;msgfmt -o django.mo django.po&#xA;msgfmt -o djangojs.mo djangojs.po&#xA;&#xA;Более простой и быстрый вариант: временно поменять язык по умолчанию на en, выполнить compilemessages, поменять язык обратно.&#xA;&#xA;Наверное надо создать соответствующий баг в трекере Django, если дойдут руки, дополню пост.&#xA;&#xA;#django #python #gettext]]&gt;</description>
      <content:encoded><![CDATA[<p>Если вы разрабатываете сайт на языке не поддерживаемом Django, то можете столкнуться с подобной ошибкой:</p>

<pre><code>  File &#34;/home/user/.virtualenvs/laos/lib/python3.7/site-packages/django/utils/translation/trans_real.py&#34;, line 102, in __init__
    raise IOError(&#34;No translation files found for default language %s.&#34; % settings.LANGUAGE_CODE)
OSError: No translation files found for default language lo.
</code></pre>

<p>Язык в <code>settings.py</code> определён правильно, ошибка довольно загадочная, и поиск не даёт разумных результатов.</p>

<p>Если попытаться скомпилировать переводы командой <code>compilemessages</code>, то она естественно не выполняется с той же самой ошибкой.</p>

<p>Самый простой способ обхода: перейти в каталог с переводами для данного языка и скомпилировать переводы вручную:</p>

<pre><code>cd locale/lo/LC_MESSAGES
msgfmt -o django.mo django.po
msgfmt -o djangojs.mo djangojs.po
</code></pre>

<p>Более простой и быстрый вариант: временно поменять язык по умолчанию на <code>en</code>, выполнить <code>compilemessages</code>, поменять язык обратно.</p>

<p>Наверное надо создать соответствующий баг в трекере Django, если дойдут руки, дополню пост.</p>

<p>#django #python #gettext</p>
]]></content:encoded>
      <guid>https://emorozov.net/reshenie-oshibki-django-oserror-no-translation-files-found-for-default-language</guid>
      <pubDate>Tue, 04 Jun 2019 09:40:01 +0000</pubDate>
    </item>
  </channel>
</rss>