Pergunta

Parece que eles cancelada em Python 3 todo o caminho fácil para rapidamente carregar um script removendo execfile()

Existe uma alternativa óbvia que eu estou ausente?

Foi útil?

Solução

acordo com a documentação , em vez de

execfile("./filename") 

Use

exec(open("./filename").read())

Veja:

Outras dicas

Você está apenas suposto ler o arquivo e exec o código você mesmo. 2to3 substitui atuais

execfile("somefile.py", global_vars, local_vars)

como

with open("somefile.py") as f:
    code = compile(f.read(), "somefile.py", 'exec')
    exec(code, global_vars, local_vars)

(A chamada de compilação não é estritamente necessário, mas ele associa o nome do arquivo com o objeto código de fazer a depuração de um pouco mais fácil.)

Veja:

Enquanto exec(open("filename").read()) muitas vezes é dado como uma alternativa para execfile("filename"), ele perde detalhes importantes que execfile suportadas.

A função a seguir para Python3.x é o mais perto que eu poderia começar a ter o mesmo comportamento que a execução de um arquivo diretamente. Isso partidas correndo python /path/to/somefile.py.

def execfile(filepath, globals=None, locals=None):
    if globals is None:
        globals = {}
    globals.update({
        "__file__": filepath,
        "__name__": "__main__",
    })
    with open(filepath, 'rb') as file:
        exec(compile(file.read(), filepath, 'exec'), globals, locals)

# execute the file
execfile("/path/to/somefile.py")

Notas:

  • Usa leitura binária para evitar codificação problemas
  • Garantido para fechar o arquivo (Python3.x adverte sobre isso)
  • Define __main__, alguns scripts dependem deste para verificar se eles são o carregamento como um módulo ou não para por exemplo. if __name__ == "__main__"
  • Definir __file__ é mais agradável para mensagens de exceção e alguns scripts usam __file__ para obter os caminhos de outros arquivos relativos a eles.
  • Toma globals opcionais e habitantes locais argumentos, modificá-los no local como execfile faz -. Assim você pode acessar quaisquer variáveis ??definidas através da leitura de volta as variáveis ??depois de executar

  • Ao contrário execfile de python2 isto significa não modificar o namespace atual por padrão. Por que você tem que passar explicitamente no globals() & locals().

Como sugeriu na python-dev mailinglist recentemente, o runpy módulo pode ser uma alternativa viável. Citando a mensagem:

https://docs.python.org/3/library/ runpy.html # runpy.run_path

import runpy
file_globals = runpy.run_path("file.py")

Existem diferenças sutis para execfile:

  • run_path sempre cria um novo namespace. Ele executa o código como um módulo, então não há nenhuma diferença entre globals e moradores (que é por isso que há apenas um argumento init_globals). Os globals são devolvidos.

    execfile executado no namespace atual ou o namespace dado. A semântica de locals e globals, se for dada, foram semelhantes aos habitantes locais e globais dentro de uma definição de classe.

  • run_path não só pode executar arquivos, mas também ovos e diretórios (consulte a sua documentação para mais detalhes).

Este é o melhor, uma vez que leva os globals e moradores do chamador:

import sys
def execfile(filename, globals=None, locals=None):
    if globals is None:
        globals = sys._getframe(1).f_globals
    if locals is None:
        locals = sys._getframe(1).f_locals
    with open(filename, "r") as fh:
        exec(fh.read()+"\n", globals, locals)

Você pode escrever sua própria função:

def xfile(afile, globalz=None, localz=None):
    with open(afile, "r") as fh:
        exec(fh.read(), globalz, localz)

Se você realmente precisava ...

Se o script que deseja carga está no mesmo diretório que o que você correr, talvez "importação" vai fazer o trabalho?

Se você precisa de código de importação de forma dinâmica o built-in função __ importação __ eo módulo imp valem a pena olhar.

>>> import sys
>>> sys.path = ['/path/to/script'] + sys.path
>>> __import__('test')
<module 'test' from '/path/to/script/test.pyc'>
>>> __import__('test').run()
'Hello world!'

test.py:

def run():
        return "Hello world!"

Se você estiver usando Python 3.1 ou posterior, você também deve dar uma olhada em importlib .

Aqui está o que eu tinha (file já está atribuído ao caminho para o arquivo com o código fonte em ambos os exemplos):

execfile(file)

Aqui está o que eu substituí-lo com:

exec(compile(open(file).read(), file, 'exec'))

A minha parte favorita:. A segunda versão funciona muito bem tanto em Python 2 e 3, o que significa que não é necessário adicionar na lógica dependente da versão

Note que o padrão acima falhará se você estiver usando PEP-263 de codificação de declarações que não são ASCII ou UTF-8. Você precisa encontrar a codificação dos dados, e codificá-lo corretamente antes de entregá-lo para exec ().

class python3Execfile(object):
    def _get_file_encoding(self, filename):
        with open(filename, 'rb') as fp:
            try:
                return tokenize.detect_encoding(fp.readline)[0]
            except SyntaxError:
                return "utf-8"

    def my_execfile(filename):
        globals['__file__'] = filename
        with open(filename, 'r', encoding=self._get_file_encoding(filename)) as fp:
            contents = fp.read()
        if not contents.endswith("\n"):
            # http://bugs.python.org/issue10204
            contents += "\n"
        exec(contents, globals, globals)

Além disso, embora não seja uma solução Python puro, se você estiver usando IPython (como você provavelmente deve de qualquer maneira), você pode fazer:

%run /path/to/filename.py

O que é igualmente fácil.

Eu sou apenas um novato aqui talvez por isso é pura sorte se eu encontrei isto:

Depois de tentar executar um script do intérprete pronta >>> com o comando

    execfile('filename.py')

para o qual eu tenho um "NameError: nome 'execfile' não está definido" Eu tentei um muito básico

    import filename

funcionou bem: -)

Espero que este pode ser útil e agradeço a todos por grandes dicas, exemplos e todas as peças magistral de código comentado que são uma grande inspiração para os recém-chegados!

Eu uso o Ubuntu LTS 16,014 x64. Python 3.5.2 (padrão, 17 de novembro de 2016, 17:05:23) [GCC 5.4.0 20160609] no linux

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top