Werkzeug: Reloader, python -m и sys.path

Созданный на 11 нояб. 2013  ·  12Комментарии  ·  Источник: pallets/werkzeug

См. Https://github.com/Kozea/WeasyPrint/issues/133

Что происходит:

  • python -m weasyprint.navigator запускается
  • [sys.executable] + sys.argv равно ['…/python', '…/weasyprint/navigator.py']
  • Таким образом перезагрузчик порождает подпроцесс
  • У дочернего процесса нет -m , поэтому Python добавляет родительский каталог файла .py в sys.path
  • Werkzeug пытается импортировать html.entities stdlib
  • Это неправильно импортирует weasyprint/html.py
  • Вещи ломаются

Здесь никто явно не делает ничего плохого. Как вы предлагаете справиться с этой ситуацией? Что вы думаете о том, чтобы …/weasyprint/navigator.py (который, как ожидается, будет в основном использоваться с python -m ) удалит родительский каталог из sys.path если он там есть?

bug reloader

Самый полезный комментарий

У меня аналогичная проблема, когда относительный импорт не выполняется, потому что перезагрузчик выполняет модуль как не-пакет:

$ python -m myapp.entrypoints.website
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
Traceback (most recent call last):
  File "/tmp/myapp/entrypoints/website.py", line 9, in <module>
    from . import mymodule
ValueError: Attempted relative import in non-package

Используя комментарии от @untitaker , в Python <3.3 мы можем определить, использовался ли python -m (только тогда определяется __loader__ ), и заставить перезагрузчик также использовать его, сбросив sys.argv :

try:
    sys.argv = ['-m', __loader__.fullname] + sys.argv[1:]
except NameError:
    pass

Но это довольно хитрый обходной путь (и только для Python <3.3).

Текущая реализация в # 531 не решает эту конкретную проблему, и, к сожалению, я не понимаю, как это сделать.

Все 12 Комментарий

Я не думаю, что это не повредит, если Werkzeug породит подпроцесс с фактически теми же аргументами, используя __loader__.fullname в Python 2 и __loader__.name в Python 3, если он существует.

@untitaker , я не понимаю о чем ты. Что __loader__ ?

Можем ли мы определить в Python, использовался ли python -m somemodule или нет?

Я прочитал ответ на StackOverflow, в котором объяснялось, как получить текущее имя модуля. Простой тест показывает, что в Python 2 доступен __loader__.fullname :

print(__loader__.fullname)

Глобальный __loader__ не существует, если файл Python выполняется без -m , а также он не существует в импортированных модулях.

В Python 3, как модуль выполнен с -m и любые другие импортируемые модули , кажется, есть __loader__ глобальный, то fullname атрибут теперь name . Но внутри каждого модуля атрибут name имеет значение модуля _current_.

Итак, в Python 2 мы _ можем_ определить, работаем ли мы с -m , но не с 3.

Кроме того, обнаружение также очень ограничено, поэтому вы можете обнаружить внутри непосредственно выполняемого модуля, только если python -m использовалось, проверяя переменную __loader__ . Кроме того, это поведение кажется скудно документированным, поэтому я не уверен, что мы все равно хотим этого в Werkzeug.

Я только что сам столкнулся с этой ошибкой. Я ожидал, что флаг -m будет присутствовать в sys.argv , но это определенно не так.

Есть ли какое-нибудь обходное решение для этого?

Да, один представлен в https://github.com/mitsuhiko/flask/issues/1246.

9 июля 2015 г., 15:08:30 CEST, Уэйн Вернер [email protected] написал:

Я только что сам столкнулся с этой ошибкой. Я ожидал, что флаг -m будет
присутствует в sys.argv , но это определенно не так.

Есть ли какое-нибудь обходное решение для этого?


Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/mitsuhiko/werkzeug/issues/461#issuecomment -119955695

Отправлено с моего устройства Android с помощью K-9 Mail. Прошу прощения за краткость.

У меня аналогичная проблема, когда относительный импорт не выполняется, потому что перезагрузчик выполняет модуль как не-пакет:

$ python -m myapp.entrypoints.website
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
Traceback (most recent call last):
  File "/tmp/myapp/entrypoints/website.py", line 9, in <module>
    from . import mymodule
ValueError: Attempted relative import in non-package

Используя комментарии от @untitaker , в Python <3.3 мы можем определить, использовался ли python -m (только тогда определяется __loader__ ), и заставить перезагрузчик также использовать его, сбросив sys.argv :

try:
    sys.argv = ['-m', __loader__.fullname] + sys.argv[1:]
except NameError:
    pass

Но это довольно хитрый обходной путь (и только для Python <3.3).

Текущая реализация в # 531 не решает эту конкретную проблему, и, к сожалению, я не понимаю, как это сделать.

Я думаю, что однажды я пытался исправить это с помощью загрузчика , но он показал значительно
разное поведение от 2 до 3.

10 сентября 2015 г., в 13:26:56 -0700, Мартин Вермаат написал:

У меня аналогичная проблема, когда относительный импорт не выполняется, потому что перезагрузчик выполняет модуль как не-пакет:

$ python -m myapp.entrypoints.website
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
Traceback (most recent call last):
  File "/tmp/myapp/entrypoints/website.py", line 9, in <module>
    from . import mymodule
ValueError: Attempted relative import in non-package

Используя комментарии от @untitaker , в Python <3.3 мы можем определить, использовался ли python -m (только тогда определяется __loader__ ), и заставить перезагрузчик также использовать его, сбросив sys.argv :

try:
    sys.argv = ['-m', __loader__.fullname] + sys.argv[1:]
except NameError:
    pass

Но это довольно хитрый обходной путь (и только для Python <3.3).


Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/mitsuhiko/werkzeug/issues/461#issuecomment -139369694

Грустно,

$ python -m werkzeug.serving weasyprint. навигатор: приложение --reload --debug

  • Запуск на http://127.0.0.1 : 5000 / (для выхода нажмите CTRL + C)
  • Перезапуск со stat
    Отслеживание (последний вызов последний):
    Файл "/usr/lib/python2.7/site-packages/werkzeug/serving.py", строка 45, в
    из ._compat импортировать PY2
    ValueError: Попытка относительного импорта вне пакета

Эта ошибка python не может быть исправлена ​​должным образом с помощью python, поэтому я предлагаю предоставить консольный скрипт

Какие-нибудь изменения в этом? Только что столкнулся с этой проблемой ... (Python 3.6, без weasyprint, просто python -m werkzeug.serving app:application )

Мне удалось обойти проблему, выполнив что-то вроде:

PYTHONPATH=$PWD:$PYTHONPATH python -m myapp.entrypoints.website

_Edit: понял, что решение было чуть выше : arrow_up: _

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

davidism picture davidism  ·  9Комментарии

abathur picture abathur  ·  13Комментарии

alexandres picture alexandres  ·  41Комментарии

asottile picture asottile  ·  11Комментарии

penner42 picture penner42  ·  19Комментарии