¿Cómo puedo cargar un módulo de Python dada su ruta completa? Tenga en cuenta que el archivo puede estar en cualquier parte del sistema de archivos, ya que es una opción de configuración.
¿Cómo puedo cargar un módulo de Python dada su ruta completa? Tenga en cuenta que el archivo puede estar en cualquier parte del sistema de archivos, ya que es una opción de configuración.
Respuestas:
Para Python 3.5+ use:
import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()
Para Python 3.3 y 3.4 use:
from importlib.machinery import SourceFileLoader
foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()
(Aunque esto ha quedado en desuso en Python 3.4.)
Para Python 2 use:
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
Hay funciones de conveniencia equivalentes para archivos compilados de Python y DLL.
Ver también http://bugs.python.org/issue21436 .
__import__
.
imp.load_source
solo establece el .__name__
del módulo devuelto. No afecta la carga.
imp.load_source()
determina la clave de la nueva entrada creada en el sys.modules
diccionario, por lo que el primer argumento sí afecta la carga.
imp
módulo está en desuso desde la versión 3.4: el imp
paquete está pendiente de desuso a favor de importlib
.
La ventaja de agregar una ruta a sys.path (sobre el uso de imp) es que simplifica las cosas al importar más de un módulo desde 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
sys.path.append
para apuntar a un único archivo de Python en lugar de un directorio?
importlib.import_module(mod_name)
se puede usar en lugar de la importación explícita aquí si no se conoce el nombre del módulo en tiempo de ejecución. Sin embargo, agregaría un sys.path.pop()
al final, suponiendo que el código importado no intente importar más módulos a medida que se usa.
Si su módulo de nivel superior no es un archivo pero 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 con el 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 retención invariable es que si tiene sys.modules ['spam'] y sys.modules ['spam.foo'] (como lo haría después de la importación anterior ), este último debe aparecer como el atributo foo del primero " como se explica aquí .
mymodule
?
/path/to/your/module/
realidad /path/to/your/PACKAGE/
? y a que mymodule
te refieres myfile.py
?
Para importar su módulo, debe agregar su directorio a la variable de entorno, ya sea temporal o permanentemente.
import sys
sys.path.append("/path/to/my/modules/")
import my_module
Agregar la siguiente línea a su .bashrc
archivo (en Linux) y ejecutar source ~/.bashrc
en el terminal:
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
Crédito / Fuente: saarrrr , otra pregunta de stackexchange
Parece que no desea importar específicamente el archivo de configuración (que tiene muchos efectos secundarios y complicaciones adicionales involucradas), 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+
result[name]
, result.get('name', default_value)
, etc.)
from runpy import run_path; from argparse import Namespace; mod = Namespace(**run_path('path/to/file.py'))
También puede hacer algo como esto y agregar el directorio en el que se encuentra el archivo de configuración en 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
def import_file(full_path_to_module):
try:
import os
module_dir, module_file = os.path.split(full_path_to_module)
module_name, module_ext = os.path.splitext(module_file)
save_cwd = os.getcwd()
os.chdir(module_dir)
module_obj = __import__(module_name)
module_obj.__file__ = full_path_to_module
globals()[module_name] = module_obj
os.chdir(save_cwd)
except:
raise ImportError
import_file('/home/somebody/somemodule.py')
except:
cláusula general rara vez es una buena idea.
save_cwd = os.getcwd()
try: …
finally: os.chdir(save_cwd)
this is already addressed by the standard library
, sí, pero Python tiene la desagradable costumbre de no ser compatible con versiones anteriores ... ya que la respuesta marcada dice que hay 2 formas diferentes antes y después de 3.3. En ese caso, preferiría escribir mi propia función universal que verificar la versión sobre la marcha. Y sí, tal vez este código no está demasiado bien protegido contra errores, pero muestra una idea (que es os.chdir (), no lo he pensado), basándome en que puedo escribir un código mejor. Por lo tanto, +1.
Aquí hay un código que funciona en todas las versiones de Python, desde 2.7-3.5 y probablemente incluso en otras.
config_file = "/tmp/config.py"
with open(config_file) as f:
code = compile(f.read(), config_file, 'exec')
exec(code, globals(), locals())
Lo probé Puede ser feo, pero hasta ahora es el único que funciona en todas las versiones.
load_source
no lo hizo porque importa el script y proporciona el acceso del script a los módulos y globales en el momento de la importación.
Se me ocurrió una versión ligeramente modificada de la maravillosa respuesta de @ SebastianRittau (para Python> 3.4, creo), que le permitirá cargar un archivo con cualquier extensión como módulo usando en spec_from_loader
lugar de spec_from_file_location
:
from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader
spec = spec_from_loader("module.name", SourceFileLoader("module.name", "/path/to/file.py"))
mod = module_from_spec(spec)
spec.loader.exec_module(mod)
La ventaja de codificar la ruta de forma explícita SourceFileLoader
es que la maquinaria no intentará averiguar el tipo de archivo desde la extensión. Esto significa que puede cargar algo como un .txt
archivo usando este método, pero no podría hacerlo spec_from_file_location
sin especificar el cargador porque .txt
no está en importlib.machinery.SOURCE_SUFFIXES
.
¿Te refieres a cargar o importar?
Puede manipular la sys.path
lista, especificar la ruta a su módulo y luego importar su módulo. Por ejemplo, dado un módulo en:
/foo/bar.py
Podrías hacerlo:
import sys
sys.path[0:0] = ['/foo'] # puts the /foo directory at the start of your path
import bar
sys.path[0:0] = ['/foo']
Explicit is better than implicit.
Entonces, ¿por qué no en sys.path.insert(0, ...)
lugar de sys.path[0:0]
?
Creo que puede usar imp.find_module()
y imp.load_module()
cargar el módulo especificado. Tendrá que separar el nombre del módulo de la ruta, es decir, si desea cargar /home/mypath/mymodule.py
debería hacer:
imp.find_module('mymodule', '/home/mypath/')
... pero eso debería hacer el trabajo.
Puede usar el pkgutil
módulo (específicamente el walk_packages
método) para obtener una lista de los paquetes en el directorio actual. A partir de ahí, es trivial usar la importlib
maquinaria para importar los módulos que desee:
import pkgutil
import importlib
packages = pkgutil.walk_packages(path='.')
for importer, name, is_package in packages:
mod = importlib.import_module(name)
# do whatever you want with module now, it's been imported!
Crear el módulo python test.py
import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3
Crear módulo de python test_check.py
from test import Client1
from test import Client2
from test import test3
Podemos importar el módulo importado desde el módulo.
¡Esta área de Python 3.4 parece ser extremadamente tortuosa de entender! Sin embargo, con un poco de pirateo usando el código de Chris Calloway como un comienzo, logré que algo funcionara. Aquí está la función básica.
def import_module_from_file(full_path_to_module):
"""
Import a module given the full path/filename of the .py file
Python 3.4
"""
module = None
try:
# Get module name and path from full path
module_dir, module_file = os.path.split(full_path_to_module)
module_name, module_ext = os.path.splitext(module_file)
# Get module "spec" from filename
spec = importlib.util.spec_from_file_location(module_name,full_path_to_module)
module = spec.loader.load_module()
except Exception as ec:
# Simple error printing
# Insert "sophisticated" stuff here
print(ec)
finally:
return module
Esto parece utilizar módulos no obsoletos de Python 3.4. No pretendo entender por qué, pero parece funcionar desde un programa. Encontré que la solución de Chris funcionaba en la línea de comando pero no desde dentro de un programa.
No digo que sea mejor, pero en aras de la exhaustividad, quería sugerir que la exec
función, disponible en python 2 y 3. le
exec
permite ejecutar código arbitrario en el ámbito global o en un ámbito interno, proporcionado como un diccionario.
Por ejemplo, si tiene un módulo almacenado en "/path/to/module
"con la función foo()
, puede ejecutarlo haciendo lo siguiente:
module = dict()
with open("/path/to/module") as f:
exec(f.read(), module)
module['foo']()
Esto hace que sea un poco más explícito que esté cargando código dinámicamente y le otorga algo de potencia adicional, como la capacidad de proporcionar incorporaciones personalizadas.
Y si tener acceso a través de los atributos, en lugar de claves, es importante para usted, puede diseñar una clase dict personalizada para los globales, que proporciona dicho acceso, por ejemplo:
class MyModuleClass(dict):
def __getattr__(self, name):
return self.__getitem__(name)
Para importar un módulo de un nombre de archivo dado, puede extender temporalmente la ruta y restaurar la ruta del sistema en la referencia de bloqueo final:
filename = "directory/module.py"
directory, module_name = os.path.split(filename)
module_name = os.path.splitext(module_name)[0]
path = list(sys.path)
sys.path.insert(0, directory)
try:
module = __import__(module_name)
finally:
sys.path[:] = path # restore
Si tenemos scripts en el mismo proyecto pero en un directorio diferente, podemos resolver este problema con el siguiente método.
En esta situación utils.py
está ensrc/main/util/
import sys
sys.path.append('./')
import src.main.util.utils
#or
from src.main.util.utils import json_converter # json_converter is example method
Esto debería funcionar
path = os.path.join('./path/to/folder/with/py/files', '*.py')
for infile in glob.glob(path):
basename = os.path.basename(infile)
basename_without_extension = basename[:-3]
# http://docs.python.org/library/imp.html?highlight=imp#module-imp
imp.load_source(basename_without_extension, infile)
name, ext = os.path.splitext(os.path.basename(infile))
. Su método funciona porque la restricción anterior a la extensión .py. Además, probablemente debería importar el módulo a alguna entrada de variable / diccionario.
Hice un paquete que usa imp
para ti. Lo llamo import_file
y así es como se usa:
>>>from import_file import import_file
>>>mylib = import_file('c:\\mylib.py')
>>>another = import_file('relative_subdir/another.py')
Puedes conseguirlo en:
http://pypi.python.org/pypi/import_file
o en
Importar módulos de paquetes en tiempo de ejecución (receta de Python)
http://code.activestate.com/recipes/223972/
###################
## #
## classloader.py #
## #
###################
import sys, types
def _get_mod(modulePath):
try:
aMod = sys.modules[modulePath]
if not isinstance(aMod, types.ModuleType):
raise KeyError
except KeyError:
# The last [''] is very important!
aMod = __import__(modulePath, globals(), locals(), [''])
sys.modules[modulePath] = aMod
return aMod
def _get_func(fullFuncName):
"""Retrieve a function object from a full dotted-package name."""
# Parse out the path, module, and function
lastDot = fullFuncName.rfind(u".")
funcName = fullFuncName[lastDot + 1:]
modPath = fullFuncName[:lastDot]
aMod = _get_mod(modPath)
aFunc = getattr(aMod, funcName)
# Assert that the function is a *callable* attribute.
assert callable(aFunc), u"%s is not callable." % fullFuncName
# Return a reference to the function itself,
# not the results of the function.
return aFunc
def _get_class(fullClassName, parentClass=None):
"""Load a module and retrieve a class (NOT an instance).
If the parentClass is supplied, className must be of parentClass
or a subclass of parentClass (or None is returned).
"""
aClass = _get_func(fullClassName)
# Assert that the class is a subclass of parentClass.
if parentClass is not None:
if not issubclass(aClass, parentClass):
raise TypeError(u"%s is not a subclass of %s" %
(fullClassName, parentClass))
# Return a reference to the class itself, not an instantiated object.
return aClass
######################
## Usage ##
######################
class StorageManager: pass
class StorageManagerMySQL(StorageManager): pass
def storage_object(aFullClassName, allOptions={}):
aStoreClass = _get_class(aFullClassName, StorageManager)
return aStoreClass(allOptions)
En Linux, agregar un enlace simbólico en el directorio donde se encuentra su script de Python funciona.
es decir:
ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py
Python creará /absolute/path/to/script/module.pyc
y lo actualizará si cambia el contenido de/absolute/path/to/module/module.py
luego incluya lo siguiente en mypythonscript.py
from module import *
git
y verificando git status
para verificar que sus cambios en el script realmente están volviendo al documento fuente y no se pierden en el éter.
He escrito mi propia función de importación global y portátil, basada en el importlib
módulo, para:
sys.path
de un almacenamiento de ruta de búsqueda.La estructura del directorio de ejemplos:
<root>
|
+- test.py
|
+- testlib.py
|
+- /std1
| |
| +- testlib.std1.py
|
+- /std2
| |
| +- testlib.std2.py
|
+- /std3
|
+- testlib.std3.py
Inclusión dependencia y orden:
test.py
-> testlib.py
-> testlib.std1.py
-> testlib.std2.py
-> testlib.std3.py
Implementación:
Última tienda de cambios: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/python/tacklelib/tacklelib.py
test.py :
import os, sys, inspect, copy
SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("test::SOURCE_FILE: ", SOURCE_FILE)
# portable import to the global space
sys.path.append(TACKLELIB_ROOT) # TACKLELIB_ROOT - path to the library directory
import tacklelib as tkl
tkl.tkl_init(tkl)
# cleanup
del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist
sys.path.pop()
tkl_import_module(SOURCE_DIR, 'testlib.py')
print(globals().keys())
testlib.base_test()
testlib.testlib_std1.std1_test()
testlib.testlib_std1.testlib_std2.std2_test()
#testlib.testlib.std3.std3_test() # does not reachable directly ...
getattr(globals()['testlib'], 'testlib.std3').std3_test() # ... but reachable through the `globals` + `getattr`
tkl_import_module(SOURCE_DIR, 'testlib.py', '.')
print(globals().keys())
base_test()
testlib_std1.std1_test()
testlib_std1.testlib_std2.std2_test()
#testlib.std3.std3_test() # does not reachable directly ...
globals()['testlib.std3'].std3_test() # ... but reachable through the `globals` + `getattr`
testlib.py :
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("1 testlib::SOURCE_FILE: ", SOURCE_FILE)
tkl_import_module(SOURCE_DIR + '/std1', 'testlib.std1.py', 'testlib_std1')
# SOURCE_DIR is restored here
print("2 testlib::SOURCE_FILE: ", SOURCE_FILE)
tkl_import_module(SOURCE_DIR + '/std3', 'testlib.std3.py')
print("3 testlib::SOURCE_FILE: ", SOURCE_FILE)
def base_test():
print('base_test')
testlib.std1.py :
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("testlib.std1::SOURCE_FILE: ", SOURCE_FILE)
tkl_import_module(SOURCE_DIR + '/../std2', 'testlib.std2.py', 'testlib_std2')
def std1_test():
print('std1_test')
testlib.std2.py :
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("testlib.std2::SOURCE_FILE: ", SOURCE_FILE)
def std2_test():
print('std2_test')
testlib.std3.py :
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("testlib.std3::SOURCE_FILE: ", SOURCE_FILE)
def std3_test():
print('std3_test')
Salida ( 3.7.4
):
test::SOURCE_FILE: <root>/test01/test.py
import : <root>/test01/testlib.py as testlib -> []
1 testlib::SOURCE_FILE: <root>/test01/testlib.py
import : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib']
import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1']
testlib.std2::SOURCE_FILE: <root>/test01/std1/../std2/testlib.std2.py
2 testlib::SOURCE_FILE: <root>/test01/testlib.py
import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']
testlib.std3::SOURCE_FILE: <root>/test01/std3/testlib.std3.py
3 testlib::SOURCE_FILE: <root>/test01/testlib.py
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib'])
base_test
std1_test
std2_test
std3_test
import : <root>/test01/testlib.py as . -> []
1 testlib::SOURCE_FILE: <root>/test01/testlib.py
import : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib']
import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1']
testlib.std2::SOURCE_FILE: <root>/test01/std1/../std2/testlib.std2.py
2 testlib::SOURCE_FILE: <root>/test01/testlib.py
import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']
testlib.std3::SOURCE_FILE: <root>/test01/std3/testlib.std3.py
3 testlib::SOURCE_FILE: <root>/test01/testlib.py
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib', 'testlib_std1', 'testlib.std3', 'base_test'])
base_test
std1_test
std2_test
std3_test
Probado en Python 3.7.4
, 3.2.5
,2.7.16
Pros :
testlib.std.py
as testlib
, testlib.blabla.py
as , testlib_blabla
etc.).sys.path
almacenamiento de rutas de búsqueda.SOURCE_FILE
y SOURCE_DIR
entre llamadas a tkl_import_module
.3.4.x
y superior] Puede mezclar los espacios de nombres del módulo en tkl_import_module
llamadas anidadas (ej .: named->local->named
o local->named->local
etc.).3.4.x
y superior] Puede exportar automáticamente variables / funciones / clases globales desde donde se declara a todos los módulos secundarios importados a través de tkl_import_module
(a través de la tkl_declare_global
función)Contras :
3.3.x
e inferior] Requiere declarar tkl_import_module
en todos los módulos a qué llamadas tkl_import_module
(duplicación de código)Actualización 1,2 (solo para versiones3.4.x
superiores):
En Python 3.4 y superior, puede omitir el requisito de declarar tkl_import_module
en cada módulo declarando tkl_import_module
en un módulo de nivel superior y la función se inyectaría a todos los módulos secundarios en una sola llamada (es una especie de importación de autodespliegue).
Actualización 3 :
Se agregó la función tkl_source_module
como análogo a bash source
con protección de ejecución de soporte en la importación (implementado a través de la fusión del módulo en lugar de la importación).
Actualización 4 :
Se agregó la función tkl_declare_global
para exportar automáticamente una variable global de módulo a todos los módulos secundarios donde una variable global de módulo no es visible porque no es parte de un módulo secundario.
Actualización 5 :
Todas las funciones se han movido a la biblioteca tacklelib, vea el enlace de arriba
Hay un paquete dedicado específicamente a esto:
from thesmuggler import smuggle
# À la `import weapons`
weapons = smuggle('weapons.py')
# À la `from contraband import drugs, alcohol`
drugs, alcohol = smuggle('drugs', 'alcohol', source='contraband.py')
# À la `from contraband import drugs as dope, alcohol as booze`
dope, booze = smuggle('drugs', 'alcohol', source='contraband.py')
Se ha probado en todas las versiones de Python (Jython y PyPy también), pero puede ser excesivo dependiendo del tamaño de su proyecto.
Agregando esto a la lista de respuestas ya que no pude encontrar nada que funcionó. Esto permitirá importar módulos compilados (pyd) de Python en 3.4:
import sys
import importlib.machinery
def load_module(name, filename):
# If the Loader finds the module name in this list it will use
# module_name.__file__ instead so we need to delete it here
if name in sys.modules:
del sys.modules[name]
loader = importlib.machinery.ExtensionFileLoader(name, filename)
module = loader.load_module()
locals()[name] = module
globals()[name] = module
load_module('something', r'C:\Path\To\something.pyd')
something.do_something()
manera bastante simple: suponga que desea importar un archivo con una ruta relativa ../../MyLibs/pyfunc.py
libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
Pero si lo logras sin guardia, finalmente puedes obtener un camino muy largo
Una solución simple que usa en importlib
lugar del imp
paquete (probado para Python 2.7, aunque también debería funcionar para Python 3):
import importlib
dirname, basename = os.path.split(pyfilepath) # pyfilepath: '/my/path/mymodule.py'
sys.path.append(dirname) # only directories should be added to PYTHONPATH
module_name = os.path.splitext(basename)[0] # '/my/path/mymodule.py' --> 'mymodule'
module = importlib.import_module(module_name) # name space of defined module (otherwise we would literally look for "module_name")
Ahora puede usar directamente el espacio de nombres del módulo importado, así:
a = module.myvar
b = module.myfunc(a)
La ventaja de esta solución es que ni siquiera necesitamos saber el nombre real del módulo que nos gustaría importar para poder usarlo en nuestro código. Esto es útil, por ejemplo, en caso de que la ruta del módulo sea un argumento configurable.
sys.path
, que no se ajusta a todos los casos de uso.
sys.path.pop()
Esta respuesta es un complemento de la respuesta de Sebastian Rittau en respuesta al comentario: "pero ¿qué pasa si no tiene el nombre del módulo?" Esta es una forma rápida y sucia de obtener el nombre probable del módulo de Python con un nombre de archivo: solo sube el árbol hasta que encuentra un directorio sin un __init__.py
archivo y luego lo vuelve a convertir en un nombre de archivo. Para Python 3.4+ (usa pathlib), lo cual tiene sentido ya que las personas Py2 pueden usar "imp" u otras formas de realizar importaciones relativas:
import pathlib
def likely_python_module(filename):
'''
Given a filename or Path, return the "likely" python module name. That is, iterate
the parent directories until it doesn't contain an __init__.py file.
:rtype: str
'''
p = pathlib.Path(filename).resolve()
paths = []
if p.name != '__init__.py':
paths.append(p.stem)
while True:
p = p.parent
if not p:
break
if not p.is_dir():
break
inits = [f for f in p.iterdir() if f.name == '__init__.py']
if not inits:
break
paths.append(p.stem)
return '.'.join(reversed(paths))
Ciertamente, hay posibilidades de mejora, y los __init__.py
archivos opcionales pueden necesitar otros cambios, pero si lo tiene __init__.py
en general, este es el truco.
La mejor forma, creo, es a partir de la documentación oficial ( 29.1. Imp - Acceda a las partes internas de importación ):
import imp
import sys
def __import__(name, globals=None, locals=None, fromlist=None):
# Fast path: see if the module has already been imported.
try:
return sys.modules[name]
except KeyError:
pass
# If any of the following calls raises an exception,
# there's a problem we can't handle -- let the caller handle it.
fp, pathname, description = imp.find_module(name)
try:
return imp.load_module(name, fp, pathname, description)
finally:
# Since we may exit via an exception, close fp explicitly.
if fp:
fp.close()