Werkzeug: Console_scripts do Windows chamados do reloader

Criado em 13 jun. 2017  ·  14Comentários  ·  Fonte: pallets/werkzeug

Estou executando o apistar no python 3 e encontrando um problema que me levou ao recarregador do werkzeug.

(fresh) C:\Users\uskaxb07\PycharmProjects\testapi>apistar run
Starting up...
 * Restarting with stat
  File "C:\Users\uskaxb07\env\fresh\Scripts\apistar.exe", line 1
SyntaxError: Non-UTF-8 code starting with '\x90' in file C:\Users\uskaxb07\env\fresh\Scripts\apistar.exe on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

Remover use_reloader da chamada para run_simple() funciona. Depois de me aprofundar em alguns comentários, descobri que https://github.com/pallets/werkzeug/blob/master/werkzeug/_reloader.py#L118 está codificando para latin1, mas apenas quando o sistema operacional é Windows e a versão python é 2. Isso poderia estar causando o erro de sintaxe não UTF-8 que estou recebendo em python3?

Todos 14 comentários

Existe um pequeno exemplo que posso usar para reproduzir isso? Não estou familiarizado com o uso do apistar e não uso o Windows regularmente.

Eu cavei um pouco mais longe. O problema é na verdade com _get_args_for_reloading () . Esse método retorna args que é ['python.exe', 'apistar.exe', 'run'] que, quando passado para subprocess.call() gera esse erro. Não é diferente de chamar python.exe apistar.exe run da linha de comando.

Portanto, o problema não é com a codificação do ambiente como eu pensava originalmente. Dado que seria uma ocorrência muito comum em outras estruturas baseadas em werkzueg, acho que uma mudança neste método para explicar o fato de que ele poderia ser chamado por meio de um .exe gerado por console_script beneficiaria todos os usuários do Windows.

Estou mudando o título do problema para explicar isso.

Se esse método descartou o elemento sys.executable de rv dentro da verificação de janelas, o recarregamento foi bem-sucedido:

def _get_args_for_reloading():
    """Returns the executable. This contains a workaround for windows
    if the executable is incorrectly reported to not have the .exe
    extension which can cause bugs on reloading.
    """
    rv = [sys.executable]
    py_script = sys.argv[0]
    if os.name == 'nt' and not os.path.exists(py_script) and \
       os.path.exists(py_script + '.exe'):
        py_script += '.exe'
        rv.pop()
    rv.append(py_script)
    rv.extend(sys.argv[1:])
    return rv

Fico feliz em revisar um PR, se você quiser enviar um.

Eu definitivamente gostaria, mas estou um pouco preso em escrever um teste para isso. Eu só posso ver isso funcionando com a biblioteca unittest.mock e patching sys.executable e os.name, mas suponho que isso não funcionaria para o seu projeto, uma vez que tem que oferecer suporte a testes automatizados em 27 também. Algum conselho?

Também qual é a estratégia de ramificação usada aqui? As solicitações de pull para problemas vão contra o ramo de manutenção atual?

Você pode ramificar de 0,12-manutenção. Vamos ver a aparência de um patch primeiro, em seguida, descobrir o teste.

Eu enviei uma solicitação pull. Parece que o Travis CI está falhando por motivos não relacionados às alterações que fiz. Este é meu primeiro Pull Request, então não sei para onde ir a partir daqui.

Isso acontecerá quando você tiver setuptools instalado lançadores exe. Se você instalar via - atualizado - pip, ele instala um novo tipo de lançadores de exe (da distlib ) que agrupam o script do iniciador no exe dentro de um zip que o Python pode executar diretamente ( documentos runpy ).

Isso não significa que não deva ser corrigido, mas é útil saber caso você não pode reproduzir isso. Isso ainda acontecerá se você instalar o Flask no modo de desenvolvimento ( pip install -e ) por exemplo.

@androiddrew @davidism alguma atualização sobre este PR?

@segevfiner você pode adicionar mais detalhes ao seu comentário mais recente? Você está sugerindo que provavelmente deveríamos corrigir a causa raiz nas ferramentas de configuração e não no Flask?

@ewpete A causa raiz é que, ao usar inicializadores gerados por ferramentas de configuração,
o sys.argv [0] não é executável como um script Python, pois é o
lançador exe. O script real é nomeado como o exe com - "-script"
anexado e o exe carrega e executa.

Observe que o exe pode ser executado diretamente (e um script Python também
com shebang que eu acredito que é o que o setuptools gera nos unices). Mas
fazer isso para scripts Python simples no Windows não é confiável (quando o
pylauncher não está instalado), uma vez que será iniciado com o arbitary Python
que está associado a arquivos .py no registro, que podem ser diferentes
do que o Python atual que estamos usando. E, claro, o mesmo se aplica a
qualquer script Python aleatório a partir do qual possamos ser chamados, que pode nem mesmo ser
executável.

pip instala em vez (via distlib) um novo tipo de iniciador exe que tem o
script de iniciador gerado anexado dentro de um zip no final do
executável. Será detectado como um arquivo zip com um script __main__.py (A
zipapp) e pode ser passado diretamente para Python para execução.

Para consertar isso nas ferramentas de configuração significará gerar um kindbof semelhante / igual
lançadores em ferramentas de configuração. E no espírito de http://xkcd.com/1172/ , este
provavelmente quebrará o código que espera os iniciadores do setuptools e tentará
usando os arquivos "* -script.py" para solucionar o problema. Eu não verifiquei
se já existe um problema / pr sobre isso.

Provavelmente não há problema em ter uma pequena solução alternativa aqui para que Werkzeug
reloader funciona mesmo na presença do estilo atual das ferramentas de configuração
lançadores. Mas isso realmente depende dos mantenedores do projeto.

בתאריך 28 de בנוב '2017 20:46, "ewpete" [email protected] כתב:

@androiddrew https://github.com/androiddrew @davidism
https://github.com/davidism alguma atualização sobre este PR?

@segevfiner https://github.com/segevfiner você pode adicionar um pouco mais
detalhe para o seu comentário mais recente? Você está sugerindo que devemos
provavelmente consertar a causa raiz em setuptools ao contrário de Flask?

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/pallets/werkzeug/issues/1136#issuecomment-347623921 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AXlg_8OSR3NdbPJzM87dyKPUAA9NpXJ6ks5s7FT7gaJpZM4N5Fcb
.a

@ewpete Este foi meu primeiro PR. Fiz o meu melhor para escrever testes, seguir o guia do desenvolvedor e colocar o PR. Não tive muita orientação sobre como fazer isso, mas fiz as alterações sugeridas nos comentários de RP. Achei que estava completo, mas nunca ouvi dizer se atendia às expectativas da equipe do projeto. Não olhei para ele desde então, e não sei o que as pessoas querem fazer com ele.

Eu tenho um tempo muito limitado em vários projetos. Não se preocupe, não se esqueça disso.

@davidism Obrigado, não apenas por responder, mas por fazer o bom trabalho de manter esses projetos vivos!

Embora isso ainda não esteja mesclado, uma possível correção temporária é fazer um monkeypatch da função _get_args_for_reloading() algum lugar antes de ser usada. No caso de um script Flask, adicioná-lo em algum lugar no início de um arquivo manage.py ajuda:

import werkzeug._reloader
import os, sys

def _get_args_for_reloading():
    rv = [sys.executable]
    py_script = sys.argv[0]
    if os.name == 'nt' and not os.path.exists(py_script) and \
       os.path.exists(py_script + '.exe'):
        py_script += '.exe'
    if os.path.splitext(rv[0])[1] == '.exe' and os.path.splitext(py_script)[1] == '.exe':
        rv.pop()
    rv.append(py_script)
    rv.extend(sys.argv[1:])
    return rv
werkzeug._reloader._get_args_for_reloading = _get_args_for_reloading
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

c17r picture c17r  ·  4Comentários

abathur picture abathur  ·  13Comentários

SimonSapin picture SimonSapin  ·  12Comentários

lepture picture lepture  ·  6Comentários

caiz picture caiz  ·  3Comentários