Parece que eles cancelaram no Python 3 toda a maneira fácil de carregar rapidamente um script removendo execfile()
Existe uma alternativa óbvia que estou perdendo?
Parece que eles cancelaram no Python 3 toda a maneira fácil de carregar rapidamente um script removendo execfile()
Existe uma alternativa óbvia que estou perdendo?
reload
está de volta, comoimp.reload
desde 3.2.%run script_name
funciona com todas as versões do Python.imp
éimportlib
(que deve ser importado):importlib.reload(mod_name)
importa e executamod_name
.runfile()
pois precisava executar um script Python que fosse executado em seu próprio espaço para nome (em vez de executar no espaço para nome que chamava ). Minha aplicação: adicione o diretório do script chamado ao caminho do sistema (sys.path
) usando o__file__
atributo: se usarmosexecfile()
ou equivalente no Python 3 (exec(open('file.py').read())
), o script incluído será executado no espaço de nomes de chamada e, portanto, será__file__
resolvido com o nome do arquivo de chamada .Respostas:
De acordo com a documentação , em vez de
Usar
Vejo:
fonte
close
lidar com esse arquivo também. Outra razão para não gostar da mudança de python 2.Você deveria ler o arquivo e executar o código sozinho. A corrente 2to3 substitui
Como
(A chamada de compilação não é estritamente necessária, mas associa o nome do arquivo ao objeto de código, facilitando um pouco a depuração.)
Vejo:
fonte
exec
seja uma declaração em python2,exec(code)
funciona porque os parâmetros são ignorados."somefile.py"
continha oinspect.getsourcefile(lambda _: None)
que estava falhando sem a compilação, porque oinspect
módulo não conseguia determinar de onde vinha o código.open("somefile.py")
pode estar incorreto sesomefile.py
usar uma codificação de caracteres diferente delocale.getpreferredencoding()
.tokenize.open()
poderia ser usado em seu lugar.Embora
exec(open("filename").read())
muitas vezes seja fornecido como uma alternativaexecfile("filename")
, ele perde detalhes importantesexecfile
suportados.A função a seguir para Python3.x é a mais próxima possível de ter o mesmo comportamento de executar um arquivo diretamente. Isso corresponde a correr
python /path/to/somefile.py
.Notas:
__main__
, alguns scripts dependem disso para verificar se estão carregando como um módulo ou não, por exemplo.if __name__ == "__main__"
__file__
é melhor para mensagens de exceção e alguns scripts são usados__file__
para obter os caminhos de outros arquivos em relação a eles.Aceita argumentos globais e locais opcionais, modificando-os no local da mesma
execfile
forma - para que você possa acessar quaisquer variáveis definidas lendo novamente as variáveis após a execução.Ao contrário do Python2,
execfile
isso não modifica o namespace atual por padrão. Para isso, você deve passar explicitamente emglobals()
&locals()
.fonte
Como sugerido recentemente na lista de discussão python-dev , o módulo runpy pode ser uma alternativa viável. Citando essa mensagem:
Existem diferenças sutis para
execfile
:run_path
sempre cria um novo espaço para nome. Ele executa o código como um módulo, portanto, não há diferença entre globais e locais (é por isso que existe apenas uminit_globals
argumento). Os globais são retornados.execfile
executado no espaço para nome atual ou no espaço para nome fornecido. A semântica delocals
eglobals
, se fornecida, era semelhante aos locais e globais dentro de uma definição de classe.run_path
pode não apenas executar arquivos, mas também ovos e diretórios (consulte a documentação para obter detalhes).fonte
file_globals
? Isso economizaria a necessidade de digitar o valorfile_globals['...']
para cada variável.Este é melhor, pois leva os globais e locais do chamador:
fonte
execfile
. Até funcionou para mim ao usar pytests onde outras soluções postadas acima falharam. Valeu! :)Você pode escrever sua própria função:
Se você realmente precisava ...
fonte
globals
elocals
apontam para o espaço para nome global do módulo que contém a definição,execfile()
e não para o espaço para nome global e local do chamador. A abordagem correta é usarNone
como valor padrão e determinar os globais e locais do chamador por meio dos recursos de introspecção doinspect
módulo.Se o script que você deseja carregar estiver no mesmo diretório que o que você executa, talvez "importar" faça o trabalho?
Se você precisar importar código dinamicamente, vale a pena examinar a função interna __ import__ e o módulo imp .
test.py:
Se você estiver usando o Python 3.1 ou posterior, verifique também o importlib .
fonte
importlib
dev.to/0xcrypto/dynamic-importing-stuff-in-python--1805Aqui está o que eu tinha (
file
já está atribuído ao caminho do arquivo com o código fonte nos dois exemplos):Aqui está o que eu substituí por:
Minha parte favorita: a segunda versão funciona muito bem no Python 2 e 3, o que significa que não é necessário adicionar uma lógica dependente da versão.
fonte
Observe que o padrão acima falhará se você estiver usando declarações de codificação PEP-263 que não são ascii ou utf-8. Você precisa encontrar a codificação dos dados e codificá-los corretamente antes de entregá-los a exec ().
fonte
Além disso, embora não seja uma solução Python pura, se você estiver usando IPython (como provavelmente deveria), você pode:
O que é igualmente fácil.
fonte
Eu sou apenas um novato aqui, então talvez seja pura sorte se eu encontrar isso:
Depois de tentar executar um script no prompt do intérprete >>> com o comando
para o qual eu recebi um "NameError: name 'execfile' não está definido", tentei um método muito básico
funcionou bem :-)
Espero que isso possa ser útil e obrigado a todos pelas ótimas dicas, exemplos e todos os trechos de código comentados por especialistas que são uma ótima inspiração para os novatos!
Eu uso o Ubuntu 16.014 LTS x64. Python 3.5.2 (padrão, 17 de novembro de 2016, 17:05:23) [GCC 5.4.0 20160609] no linux
fonte
Para mim, a abordagem mais limpa é usar
importlib
e importar o arquivo como módulo por caminho, assim:Exemplo de uso
Vamos ter um arquivo
foo.py
:Agora basta importar e usá-lo como um módulo normal:
Eu prefiro essa técnica a abordagens diretas, como
exec(open(...))
porque ela não bagunça seus espaços de nome ou mexe desnecessariamente$PATH
.fonte