Execução de código Python com opção -m ou não
Use a -m
bandeira.
Os resultados são praticamente os mesmos quando você tem um script, mas quando você desenvolve um pacote, sem o -m
sinalizador, não há como fazer as importações funcionarem corretamente se você deseja executar um subpacote ou módulo no pacote como a entrada principal aponte para o seu programa (e acredite, eu tentei.)
Os docs
Como os documentos na sinalização -m dizem:
Pesquise sys.path para o módulo nomeado e execute seu conteúdo como o __main__
módulo.
e
Tal como acontece com a opção -c, o diretório atual será adicionado ao início de sys.path.
tão
python -m pdb
é aproximadamente equivalente a
python /usr/lib/python3.5/pdb.py
(presumindo que você não tenha um pacote ou script em seu diretório atual chamado pdb.py)
Explicação:
O comportamento é tornado "deliberadamente semelhante a" scripts.
Muitos módulos de biblioteca padrão contêm código que é chamado em sua execução como um script. Um exemplo é o módulo timeit:
Algum código Python deve ser executado como um módulo: (acho que este exemplo é melhor do que o exemplo de documento de opção de linha de comando)
$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop
$ python -m timeit '"-".join([str(n) for n in range(100)])'
10000 loops, best of 3: 33.4 usec per loop
$ python -m timeit '"-".join(map(str, range(100)))'
10000 loops, best of 3: 25.2 usec per loop
E a partir dos destaques da nota de lançamento para Python 2.4 :
A opção de linha de comando -m - python -m modulename encontrará um módulo na biblioteca padrão e o invocará. Por exemplo, python -m pdb
é equivalente apython /usr/lib/python2.4/pdb.py
Questão a seguir
Além disso, David Beazley Python Essential Reference explica como "A opção -m executa um módulo de biblioteca como um script que é executado dentro do __main__
módulo antes da execução do script principal".
Isso significa que qualquer módulo que você pode consultar com uma instrução de importação pode ser executado como o ponto de entrada do programa - se ele tiver um bloco de código, geralmente próximo ao final, com if __name__ == '__main__':
.
-m
sem adicionar o diretório atual ao caminho:
Um comentário aqui em outro lugar diz:
O fato da opção -m também adicionar o diretório atual ao sys.path é obviamente um problema de segurança (consulte: ataque de pré-carregamento). Esse comportamento é semelhante à ordem de pesquisa da biblioteca no Windows (antes de ter sido reforçada recentemente). É uma pena que o Python não siga a tendência e não ofereça uma maneira simples de desativar a adição. para sys.path
Bem, isso demonstra o possível problema - (no Windows, remova as aspas):
echo "import sys; print(sys.version)" > pdb.py
python -m pdb
3.5.2 |Anaconda 4.1.1 (64-bit)| (default, Jul 5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)]
Use a -I
sinalização para bloquear isso para ambientes de produção (novo na versão 3.4):
python -Im pdb
usage: pdb.py [-c command] ... pyfile [arg] ...
etc...
dos documentos :
-I
Execute o Python no modo isolado. Isso também implica -E e -s. No modo isolado, sys.path não contém o diretório do script nem o diretório de pacotes do site do usuário. Todas as variáveis de ambiente PYTHON * também são ignoradas. Outras restrições podem ser impostas para evitar que o usuário injete código malicioso.
O que __package__
fazer?
Ele permite importações relativas explícitas, embora não particularmente pertinentes a essa pergunta - veja esta resposta aqui: Qual é o propósito do atributo "__package__" em Python?
PYTHONPATH=test python -m foo.bar
? Você poderia explicar em detalhes, por favor?