Werkzeug: Reloader, python -m e sys.path

Criado em 11 nov. 2013  ·  12Comentários  ·  Fonte: pallets/werkzeug

Veja https://github.com/Kozea/WeasyPrint/issues/133

O que está acontecendo é:

  • python -m weasyprint.navigator é executado
  • [sys.executable] + sys.argv é ['…/python', '…/weasyprint/navigator.py']
  • O recarregador gera um subprocesso dessa maneira
  • O processo filho não tem -m , então Python adiciona o diretório pai do arquivo .py a sys.path
  • Werkzeug tenta importar html.entities do stdlib
  • Isso importa weasyprint/html.py incorretamente
  • Quebras de coisas

Ninguém aqui está fazendo nada obviamente errado. Como você sugere lidar com esta situação? O que você acha de ter …/weasyprint/navigator.py (que deve ser usado principalmente com python -m ) remover seu diretório pai de sys.path se ele estiver lá?

bug reloader

Comentários muito úteis

Tenho um problema semelhante, em que as importações relativas falham porque o recarregador executa o módulo como um não pacote:

$ 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

Usando os comentários de @untitaker , no Python <3.3 podemos detectar se python -m foi usado (somente então __loader__ definido) e forçar o recarregador a também usá-lo redefinindo sys.argv :

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

Mas esta é uma solução bastante hacky (e apenas para Python <3.3).

A implementação atual em # 531 não corrige esse problema específico e, infelizmente, não vejo como isso poderia ser feito.

Todos 12 comentários

Não acho que não faria mal se Werkzeug gerasse o subprocesso com realmente os mesmos argumentos, usando __loader__.fullname no Python 2 e __loader__.name no Python 3, se existente.

@untitaker , não entendo o que você quer dizer. O que é __loader__ ?

Podemos detectar em Python se python -m somemodule foi usado ou não?

Eu encontrei uma resposta StackOverflow que explicava como obter o nome do módulo atual. Um teste simples mostra que em Python 2, __loader__.fullname está disponível:

print(__loader__.fullname)

O __loader__ global não existe se o arquivo Python é executado sem -m , e também não existe nos módulos importados.

No Python 3, tanto o módulo executado com -m quanto quaisquer outros módulos importados parecem ter um __loader__ global, o atributo fullname agora é name . Mas dentro de cada módulo, o atributo name tem o valor do módulo _current_.

Portanto, no Python 2 nós _podemos_ detectar se estamos executando com -m , mas não no 3.

Além disso, a detecção é muito limitada, então você só pode detectar dentro do módulo executado diretamente se python -m foi usado verificando a variável __loader__ . Além disso, esse comportamento parece pouco documentado, então não tenho certeza se é isso que queremos em Werkzeug de qualquer maneira.

Acabei de encontrar esse bug sozinho. Eu esperava que a bandeira -m estivesse presente em sys.argv , mas definitivamente não está.

Existe algum tipo de solução alternativa para isso?

Sim, um é apresentado em https://github.com/mitsuhiko/flask/issues/1246

Em 9 de julho de 2015, 15:08:30 CEST, Wayne Werner [email protected] escreveu:

Acabei de encontrar esse bug sozinho. Eu esperava que a bandeira -m fosse
presente em sys.argv , mas definitivamente não é.

Existe algum tipo de solução alternativa para isso?


Responda a este e-mail diretamente ou visualize-o no GitHub:
https://github.com/mitsuhiko/werkzeug/issues/461#issuecomment -119955695

Enviado do meu dispositivo Android com K-9 Mail. Por favor desculpe minha brevidade.

Tenho um problema semelhante, em que as importações relativas falham porque o recarregador executa o módulo como um não pacote:

$ 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

Usando os comentários de @untitaker , no Python <3.3 podemos detectar se python -m foi usado (somente então __loader__ definido) e forçar o recarregador a também usá-lo redefinindo sys.argv :

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

Mas esta é uma solução bastante hacky (e apenas para Python <3.3).

A implementação atual em # 531 não corrige esse problema específico e, infelizmente, não vejo como isso poderia ser feito.

Acho que tentei consertar isso com o loader uma vez, mas ele mostrou muito
comportamento diferente de 2 a 3.

Na quinta-feira, 10 de setembro de 2015 às 13:26:56 -0700, Martijn Vermaat escreveu:

Tenho um problema semelhante, em que as importações relativas falham porque o recarregador executa o módulo como um não pacote:

$ 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

Usando os comentários de @untitaker , no Python <3.3 podemos detectar se python -m foi usado (somente então __loader__ definido) e forçar o recarregador a também usá-lo redefinindo sys.argv :

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

Mas esta é uma solução bastante hacky (e apenas para Python <3.3).


Responda a este e-mail diretamente ou visualize-o no GitHub:
https://github.com/mitsuhiko/werkzeug/issues/461#issuecomment -139369694

Tristemente,

$ python -m werkzeug.serving weasyprint. navegador: app --reload --debug

  • Executando em http://127.0.0.1 : 5000 / (pressione CTRL + C para sair)
  • Reiniciando com estatísticas
    Traceback (última chamada mais recente):
    Arquivo "/usr/lib/python2.7/site-packages/werkzeug/serving.py", linha 45, em
    from ._compat import PY2
    ValueError: Tentativa de importação relativa em não pacote

Este bug do python não pode ser corrigido apropriadamente com python, então eu sugiro fornecer um script de console

Alguma mudança nisso? Acabei de encontrar este problema ... (Python 3.6, sem weasyprint, apenas python -m werkzeug.serving app:application )

Consegui contornar o problema fazendo algo como:

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

_Editar: percebi que a solução estava logo acima : arrow_up: _

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

lepture picture lepture  ·  6Comentários

sorenh picture sorenh  ·  4Comentários

davidism picture davidism  ·  9Comentários

asottile picture asottile  ·  11Comentários

mhelmetag picture mhelmetag  ·  8Comentários