derfred
¿Cómo cargo un módulo de Python dada su ruta completa?
Tenga en cuenta que el archivo puede estar en cualquier parte del sistema de archivos donde el usuario tenga derechos de acceso.
Ver también: ¿Cómo importar un módulo dado su nombre como cadena?
La ventaja de agregar una ruta a sys.path (en lugar de usar imp) es que simplifica las cosas al importar más de un módulo de un solo paquete. Por ejemplo:
import sys
# the mock-0.3.1 dir contains testcase.py, testutils.py & mock.py
sys.path.append('/foo/bar/mock-0.3.1')
from testcase import TestCase
from testutils import RunTests
from mock import Mock, sentinel, patch
-
¿Cómo usamos
sys.path.append
para apuntar a un solo archivo de python en lugar de un directorio?– Fani
13 de enero de 2014 a las 17:46
-
🙂 Quizás su pregunta sería más adecuada como una pregunta de StackOverflow, no como un comentario sobre una respuesta.
– Daryl Spitzer
6 de marzo de 2015 a las 0:12
-
La ruta de python puede contener archivos zip, “eggs” (un tipo complejo de archivos zip), etc. Los módulos se pueden importar de ellos. Así que los elementos de la ruta son de hecho contenedores de archivos, pero no necesariamente son directorios.
– alexis
30/04/2015 a las 21:21
-
Tenga cuidado con el hecho de que Python almacena en caché las declaraciones de importación. En el raro caso de que tenga dos carpetas diferentes que compartan un solo nombre de clase (classX), el enfoque de agregar una ruta a sys.path, importar classX, eliminar la ruta y repetir para las rutas restantes no funcionará. Python siempre cargará la clase desde la primera ruta desde su caché. En mi caso, mi objetivo era crear un sistema de complementos donde todos los complementos implementaran una clase X específica. Terminé usando SourceFileLoader, tenga en cuenta que es la desaprobación es controvertida.
– ComFreek
3 de julio de 2015 a las 17:18
-
Tenga en cuenta que este enfoque permite que el módulo importado importe otros módulos desde el mismo directorio, lo que los módulos suelen hacer, mientras que el enfoque de la respuesta aceptada no lo hace (al menos en 3.7).
importlib.import_module(mod_name)
se puede usar en lugar de la importación explícita aquí si el nombre del módulo no se conoce en tiempo de ejecución, agregaría unsys.path.pop()
al final, sin embargo, suponiendo que el código importado no intente importar más módulos a medida que se usa.– Eli_B
6 mayo 2019 a las 21:45
-
Esta solución “temporal” es una excelente respuesta si desea impulsar un proyecto en un cuaderno jupyter en otro lugar.
– Ford
16 de noviembre de 2018 a las 17:20
-
Pero… es peligroso manipular el camino.
– Shai Alon
10 de noviembre de 2019 a las 15:56
-
@ShaiAlon Está agregando rutas, por lo que no hay más peligro que cuando transfiere códigos de una computadora a otra, las rutas pueden estropearse. Entonces, para el desarrollo de paquetes, solo importo paquetes locales. Además, los nombres de los paquetes deben ser únicos. Si está preocupado, use la solución temporal.
– Miladiosas
13 de noviembre de 2019 a las 0:11
-
Tuve dificultades para importar mis pruebas unitarias, y su temperatura funcionó bien. Lo modifiqué para importar desde el mismo directorio que Unit Test con: >>> import os >>> import sys >>> sys.path.append(os.getcwd())
– brewmanz
19 de septiembre a las 3:45
Sam Grondahl
Si su módulo de nivel superior no es un archivo sino que está empaquetado como un directorio con __init__.py, entonces la solución aceptada casi funciona, pero no del todo. En Python 3.5+ se necesita el siguiente código (tenga en cuenta la línea agregada que comienza con ‘sys.modules’):
MODULE_PATH = "/path/to/your/module/__init__.py"
MODULE_NAME = "mymodule"
import importlib
import sys
spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
Sin esta línea, cuando se ejecuta exec_module, intenta vincular las importaciones relativas en su nivel superior __init__.py al nombre del módulo de nivel superior, en este caso, “mymodule”. Pero “mymodule” aún no está cargado, por lo que obtendrá el error “SystemError: el módulo principal ‘mymodule’ no está cargado, no puede realizar una importación relativa”. Por lo tanto, debe vincular el nombre antes de cargarlo. La razón de esto es la invariante fundamental del sistema de importación relativo: “La propiedad invariante es que si tiene sys.modules[‘spam’] y sys.módulos[‘spam.foo’] (como lo haría después de la importación anterior), el último debe aparecer como el atributo foo del primero” como se discute aquí.
-
¡Muchas gracias! Este método permite importaciones relativas entre submódulos. ¡Excelente!
– tebanep
10 oct 2019 a las 14:09
-
Esta respuesta coincide con la documentación aquí: docs.python.org/3/library/….
-Tim Ludwinski
9 de diciembre de 2019 a las 16:08
-
pero que es
mymodule
?– Gulzar
20 de enero de 2020 a las 10:02
-
@Gulzar, es el nombre que le gustaría darle a su módulo, de modo que luego pueda hacer: “from mymodule import myclass”
– Idodo
16 de febrero de 2020 a las 22:44
-
Aunque no es convencional, si el punto de entrada de su paquete es diferente a
__init__.py
, aún puede importarlo como un paquete. Incluirspec.submodule_search_locations = [os.path.dirname(MODULE_PATH)]
después de crear la especificación. También puede tratar un__init__.py
como un no paquete (por ejemplo, módulo único) estableciendo este valor enNone
– Azmísov
5 de noviembre de 2020 a las 20:32
Pedro Mortensen
Parece que no desea importar específicamente el archivo de configuración (que tiene muchos efectos secundarios y complicaciones adicionales). Solo desea ejecutarlo y poder acceder al espacio de nombres resultante. La biblioteca estándar proporciona una API específicamente para eso en forma de runpy.run_path:
from runpy import run_path
settings = run_path("/path/to/file.py")
Esa interfaz está disponible en Python 2.7 y Python 3.2+.
-
¡Muchas gracias! Este método permite importaciones relativas entre submódulos. ¡Excelente!
– tebanep
10 oct 2019 a las 14:09
-
Esta respuesta coincide con la documentación aquí: docs.python.org/3/library/….
-Tim Ludwinski
9 de diciembre de 2019 a las 16:08
-
pero que es
mymodule
?– Gulzar
20 de enero de 2020 a las 10:02
-
@Gulzar, es el nombre que le gustaría darle a su módulo, de modo que luego pueda hacer: “from mymodule import myclass”
– Idodo
16 de febrero de 2020 a las 22:44
-
Aunque no es convencional, si el punto de entrada de su paquete es diferente a
__init__.py
, aún puede importarlo como un paquete. Incluirspec.submodule_search_locations = [os.path.dirname(MODULE_PATH)]
después de crear la especificación. También puede tratar un__init__.py
como un no paquete (por ejemplo, módulo único) estableciendo este valor enNone
– Azmísov
5 de noviembre de 2020 a las 20:32
Pedro Mortensen
También puede hacer algo como esto y agregar el directorio en el que se encuentra el archivo de configuración a la ruta de carga de Python, y luego simplemente hacer una importación normal, suponiendo que conoce el nombre del archivo de antemano, en este caso “config”.
Desordenado, pero funciona.
configfile="~/config.py"
import os
import sys
sys.path.append(os.path.dirname(os.path.expanduser(configfile)))
import config
-
Eso no es dinámicamente.
– Shai Alon
10 de noviembre de 2019 a las 16:10
-
Probé: config_file = ‘setup-for-chats’, setup_file = get_setup_file(config_file + “.py”), sys.path.append(os.path.dirname(os.path.expanduser(setup_file))), import config_file >> “ImportError: ningún módulo llamado config_file”
– Shai Alon
10 de noviembre de 2019 a las 16:17
Pregunta agradable y simple, y respuestas útiles, pero me hacen preguntarme qué sucedió con el mantra de Python “Hay una obvio “manera” de hacerlo… No parece una respuesta única o simple y obvia… Parece ridículamente hacky y depende de la versión para una operación tan fundamental (y se ve más inflada en las versiones más nuevas. .).
– dedo
6 de diciembre de 2019 a las 12:08
@inger lo que sucedió con el mantra de python “Hay una forma obvia” de hacerlo […] [not] una sola o una respuesta simple y obvia a la misma […] ridículamente hacky[…] más hinchado en versiones más nuevas Bienvenido al terrible mundo de la gestión de paquetes de Python. de pitón
import
,virtualenv
,pip
,setuptools
todo lo demás debe desecharse y reemplazarse con un código de trabajo. Solo traté de asimilarvirtualenv
o erapipenv
y tuvo que trabajar a través del equivalente de un manual de Jumbo Jet. Cómo se presenta ese artilugio como La solución para lidiar con los deps se me escapa por completo.– John Fraser
26 de junio de 2020 a las 20:59
XKCD relevante xkcd.com/1987
– John Fraser
26 de junio de 2020 a las 21:08
@JohnFrazer ha empeorado por las constantes molestias de las personas que no se molestaron en leer 2 párrafos de documentación. Su XKCD no es realmente relevante, ya que muestra lo que este tipo de personas pueden lograr cuando intentan cosas hasta que algo funciona. Además, el hecho de que haya una nueva forma no significa que ahora haya “dos formas obvias”. La forma antigua es obvia para algunos casos, la nueva forma presenta facilidad de uso para otros. Eso es lo que sucede cuando realmente te preocupas por DevX.
– Blazej Michalik
2 de diciembre de 2020 a las 0:13
Y piense que Java o incluso PHP (en estos días) tienen una forma clara y simple de dividir las cosas en paquetes/espacios de nombres y reutilizarlos. Es impactante ver tanto dolor en Python, que adoptó la simplicidad en todos los demás aspectos.
– Alex
27 de enero de 2021 a las 7:46