Parece que cancelaron en Python 3 toda la manera fácil de cargar rápidamente un script eliminando execfile()
¿Hay una alternativa obvia que me falta?
Parece que cancelaron en Python 3 toda la manera fácil de cargar rápidamente un script eliminando execfile()
¿Hay una alternativa obvia que me falta?
reload
está de vuelta, comoimp.reload
, desde 3.2.%run script_name
funciona con todas las versiones de Python.imp
esimportlib
(que debe importarse):importlib.reload(mod_name)
importa y ejecutamod_name
.runfile()
ya que necesitaba ejecutar un script de Python que se ejecute en su propio espacio de nombres (en lugar de ejecutarse en el espacio de nombres de llamada ). Mi solicitud: agregar el directorio del script llamado a la ruta del sistema (sys.path
) mediante el__file__
atributo: si usamosexecfile()
o su equivalente en Python 3 (exec(open('file.py').read())
) del script incluido se ejecuta en el espacio de nombres llamando y por lo tanto__file__
resuelve al llamar a nombre de archivo.Respuestas:
Según la documentación , en lugar de
Utilizar
Ver:
fuente
close
ese identificador de archivo. Otra razón por la que no les gusta el cambio de pitón 2.Se supone que solo debes leer el archivo y ejecutar el código tú mismo. La corriente 2to3 reemplaza
como
(La llamada de compilación no es estrictamente necesaria, pero asocia el nombre de archivo con el objeto de código, lo que facilita un poco la depuración).
Ver:
fuente
exec
es una declaración en python2,exec(code)
funciona porque los padres simplemente se ignoran."somefile.py"
contenidoinspect.getsourcefile(lambda _: None)
estaba fallando sin la compilación, porque elinspect
módulo no podía determinar de dónde venía el código.open("somefile.py")
puede ser incorrecto sisomefile.py
usa una codificación de caracteres diferente delocale.getpreferredencoding()
.tokenize.open()
podría ser usado en su lugar.Si bien a
exec(open("filename").read())
menudo se ofrece como una alternativaexecfile("filename")
, se pierden detalles importantes queexecfile
respaldan.La siguiente función para Python3.x es lo más cercana posible a tener el mismo comportamiento que ejecutar un archivo directamente. Eso coincide con correr
python /path/to/somefile.py
.Notas:
__main__
, algunos scripts dependen de esto para verificar si se están cargando como un módulo o no, por ejemplo.if __name__ == "__main__"
__file__
es mejor para los mensajes de excepción y algunas secuencias de comandos se utilizan__file__
para obtener las rutas de otros archivos en relación con ellos.Toma argumentos opcionales globales y locales, modificándolos en el lugar como lo
execfile
hace, para que pueda acceder a cualquier variable definida al leer las variables después de la ejecución.A diferencia de Python2,
execfile
esto no modifica el espacio de nombres actual de forma predeterminada. Para eso tienes que pasar explícitamenteglobals()
&locals()
.fuente
Como se sugirió recientemente en la lista de correo python-dev , el módulo runpy podría ser una alternativa viable. Citando de ese mensaje:
Hay diferencias sutiles para
execfile
:run_path
siempre crea un nuevo espacio de nombres. Ejecuta el código como un módulo, por lo que no hay diferencia entre globales y locales (razón por la cual solo hay uninit_globals
argumento). Los globales son devueltos.execfile
ejecutado en el espacio de nombres actual o en el espacio de nombres dado. La semántica delocals
yglobals
, si se da, eran similares a los locales y globales dentro de una definición de clase.run_path
no solo puede ejecutar archivos, sino también huevos y directorios (consulte su documentación para más detalles).fuente
file_globals
? Esto ahorraría tener que escribir elfile_globals['...']
para cada variable.Este es mejor, ya que toma los globales y locales de la persona que llama:
fuente
execfile
. Incluso funcionó para mi cuando uso pytests donde otras soluciones publicadas anteriormente fallaron. ¡Gracias! :)Podrías escribir tu propia función:
Si realmente necesitaras ...
fuente
globals
, ylocals
apuntan al espacio de nombres global fo el módulo que contiene la definición delexecfile()
lugar de espacio de nombres global y local de la persona que llama. El enfoque correcto es usarNone
como valor predeterminado y determinar los globales y locales de la persona que llama a través de las capacidades de introspección delinspect
módulo.Si el script que desea cargar está en el mismo directorio que el que ejecuta, ¿tal vez "import" hará el trabajo?
Si necesita importar código dinámicamente, vale la pena mirar la función incorporada __ import__ y el módulo imp .
test.py:
Si está utilizando Python 3.1 o posterior, también debería echar un vistazo a importlib .
fuente
importlib
dev.to/0xcrypto/dynamic-importing-stuff-in-python--1805Esto es lo que tenía (
file
ya está asignado a la ruta del archivo con el código fuente en ambos ejemplos):Esto es con lo que lo reemplacé:
Mi parte favorita: la segunda versión funciona bien tanto en Python 2 como en 3, lo que significa que no es necesario agregar lógica dependiente de la versión.
fuente
Tenga en cuenta que el patrón anterior fallará si está utilizando declaraciones de codificación PEP-263 que no son ascii o utf-8. Debe encontrar la codificación de los datos y codificarla correctamente antes de entregarla a exec ().
fuente
Además, aunque no es una solución pura de Python, si está utilizando IPython (como probablemente debería hacerlo de todos modos), puede hacer lo siguiente:
Lo cual es igualmente fácil.
fuente
Solo soy un novato aquí, así que tal vez sea pura suerte si encuentro esto:
Después de intentar ejecutar un script desde el indicador del intérprete >>> con el comando
para lo cual obtuve un "NameError: el nombre 'execfile' no está definido" Intenté un método muy básico
funcionó bien :-)
¡Espero que esto pueda ser útil y gracias a todos por las excelentes sugerencias, ejemplos y todas esas piezas de código magistralmente comentadas que son una gran inspiración para los recién llegados!
Yo uso Ubuntu 16.014 LTS x64. Python 3.5.2 (predeterminado, 17 de noviembre de 2016, 17:05:23) [GCC 5.4.0 20160609] en Linux
fuente
Para mí, el enfoque más limpio es usar
importlib
e importar el archivo como un módulo por ruta, así:Ejemplo de uso
Tengamos un archivo
foo.py
:Ahora solo importe y use como un módulo normal:
Prefiero esta técnica sobre los enfoques directos, como
exec(open(...))
porque no abarrota sus espacios de nombres o se mete innecesariamente con ellos$PATH
.fuente