Wie kann ich ein Python -Modul mit vollem Pfad laden? Beachten Sie, dass sich die Datei an einer beliebigen Stelle im Dateisystem befinden kann, da es sich um eine Konfigurationsoption handelt.
Für Python 3.5+ verwenden Sie:
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()
Für Python 3.3 und 3.4 verwenden Sie:
from importlib.machinery import SourceFileLoader
foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()
(Obwohl dies in Python 3.4 veraltet ist.)
Für Python 2 verwenden Sie:
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
Es gibt entsprechende Komfortfunktionen für kompilierte Python -Dateien und DLLs.
Siehe auch http://bugs.python.org/issue21436 .
Der Vorteil des Hinzufügens eines Pfades zu sys.path (anstelle von imp) besteht darin, dass der Import mehrerer Module aus einem einzelnen Paket vereinfacht wird. Zum Beispiel:
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
Es hört sich so an, als ob Sie die Konfigurationsdatei nicht speziell importieren möchten (was viele Nebenwirkungen und zusätzliche Komplikationen mit sich bringt), sondern sie nur ausführen und auf den resultierenden Namespace zugreifen möchten. Die Standardbibliothek bietet speziell dafür eine API in Form von runpy.run_path :
from runpy import run_path
settings = run_path("/path/to/file.py")
Diese Schnittstelle ist in Python 2.7 und Python 3.2+ verfügbar
Wenn Ihr Top-Level-Modul keine Datei ist, sondern als Verzeichnis mit __init__.py gepackt ist, funktioniert die akzeptierte Lösung fast, aber nicht ganz. In Python 3.5+ wird der folgende Code benötigt (beachten Sie die hinzugefügte Zeile, die mit 'sys.modules' beginnt):
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)
Ohne diese Zeile versucht exec_module beim Ausführen, relative Importe in Ihrer obersten Ebene __init__.py an den Modulnamen der obersten Ebene zu binden - in diesem Fall "mymodule". "Mymodule" ist jedoch noch nicht geladen, sodass der Fehler "SystemError: Übergeordnetes Modul 'mymodule' nicht geladen, relativer Import nicht möglich" angezeigt wird. Sie müssen den Namen also binden, bevor Sie ihn laden. Der Grund dafür ist die fundamentale Invariante des relativen Importsystems: "Die Invariante besteht darin, dass Sie sys.modules ['spam'] und sys.modules ['spam.foo'] haben (wie Sie es nach dem obigen Import tun würden ), letzteres muss als foo-Attribut des ersteren erscheinen " wie hier besprochen .
Um Ihr Modul zu importieren, müssen Sie sein Verzeichnis entweder vorübergehend oder dauerhaft zur Umgebungsvariablen hinzufügen.
import sys
sys.path.append("/path/to/my/modules/")
import my_module
Hinzufügen der folgenden Zeile zu Ihrer .bashrc
-Datei (unter Linux) und Ausführen von source ~/.bashrc
im Terminal:
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
Kredit/Quelle: saarrrr , eine andere Stapelwechselfrage
Sie können auch so etwas tun und das Verzeichnis, in dem sich die Konfigurationsdatei befindet, in den Ladepfad Python einfügen und dann einfach einen normalen Import ausführen, vorausgesetzt, Sie kennen den Namen der Datei im Voraus in dieser Fall "config".
Chaotisch, aber es funktioniert.
configfile = '~/config.py'
import os
import sys
sys.path.append(os.path.dirname(os.path.expanduser(configfile)))
import config
Ich habe eine leicht modifizierte Version von @ SebastianRittaus wunderbare Antwort (für Python> 3.4, denke ich) entwickelt, mit der Sie eine Datei mit einer beliebigen Erweiterung als Modul laden können mit spec_from_loader
anstelle von 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)
_
Der Vorteil der Codierung des Pfads in einem expliziten SourceFileLoader
besteht darin, dass machinery nicht versucht, den Dateityp anhand der Erweiterung zu ermitteln. Dies bedeutet, dass Sie mit dieser Methode so etwas wie eine _.txt
_-Datei laden können, dies jedoch nicht mit _spec_from_file_location
_ ohne Angabe des Ladeprogramms, da _.txt
_ nicht in importlib.machinery.SOURCE_SUFFIXES
.
Meinen Sie Laden oder Importieren?
Sie können die Liste sys.path
bearbeiten, den Pfad zu Ihrem Modul angeben und dann Ihr Modul importieren. Zum Beispiel ein Modul gegeben an:
/foo/bar.py
Du könntest es tun:
import sys
sys.path[0:0] = ['/foo'] # puts the /foo directory at the start of your path
import bar
Hier ist ein Code, der in allen Python Versionen von 2.7-3.5 und wahrscheinlich auch in anderen Versionen funktioniert.
config_file = "/tmp/config.py"
with open(config_file) as f:
code = compile(f.read(), config_file, 'exec')
exec(code, globals(), locals())
Ich habe es getestet. Es mag hässlich sein, ist aber bisher das einzige, das in allen Versionen funktioniert.
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')
Ich glaube, Sie können imp.find_module()
und imp.load_module()
verwenden, um das angegebene Modul zu laden. Sie müssen den Modulnamen vom Pfad trennen, d. H., Wenn Sie /home/mypath/mymodule.py
laden möchten, müssen Sie Folgendes tun:
imp.find_module('mymodule', '/home/mypath/')
... aber das sollte die Arbeit erledigen.
Erstellen Sie das python -Modul test.py
import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3
Erstellen Sie das python Modul test_check.py
from test import Client1
from test import Client2
from test import test3
Wir können das importierte Modul aus dem Modul importieren.
Sie können das pkgutil
-Modul (insbesondere die walk_packages
-Methode) verwenden, um eine Liste der Pakete im aktuellen Verzeichnis abzurufen. Von dort aus ist es ganz einfach, die importlib
-Maschinerie zu verwenden, um die gewünschten Module zu importieren:
_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!
_
Das sollte funktionieren
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)
Ich sage nicht, dass es besser ist, aber der Vollständigkeit halber wollte ich die exec
-Funktion vorschlagen, die sowohl in python 2 als auch in 3. exec
verfügbar ist Führen Sie beliebigen Code entweder im globalen Bereich oder in einem internen Bereich aus, der als Wörterbuch bereitgestellt wird.
Wenn Sie beispielsweise ein Modul in "/path/to/module
"mit der Funktion foo()
gespeichert haben, können Sie es folgendermaßen ausführen:
module = dict()
with open("/path/to/module") as f:
exec(f.read(), module)
module['foo']()
Das macht es etwas expliziter, dass Sie Code dynamisch laden, und verleiht Ihnen zusätzliche Leistung, z. B. die Möglichkeit, benutzerdefinierte Buildins bereitzustellen.
Und wenn Ihnen der Zugriff über Attribute anstelle von Schlüsseln wichtig ist, können Sie eine benutzerdefinierte Diktatklasse für die Globalen entwerfen, die einen solchen Zugriff ermöglicht, z.
class MyModuleClass(dict):
def __getattr__(self, name):
return self.__getitem__(name)
Dieser Bereich von Python 3.4 scheint extrem umständlich zu sein! Mit ein bisschen Hacking und dem Code von Chris Calloway als Start gelang es mir jedoch, etwas zum Laufen zu bringen. Hier ist die Grundfunktion.
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
Dies scheint nicht veraltete Module aus Python 3.4 zu verwenden. Ich gebe nicht vor zu verstehen, warum, aber es scheint innerhalb eines Programms zu funktionieren. Ich fand, dass Chris 'Lösung auf der Kommandozeile funktionierte, aber nicht in einem Programm.
Um ein Modul aus einem bestimmten Dateinamen zu importieren, können Sie den Pfad vorübergehend erweitern und den Systempfad im finally-Block reference: wiederherstellen
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
Paketmodule zur Laufzeit importieren (Python-Rezept)
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)
Unter Linux funktioniert das Hinzufügen eines symbolischen Links in dem Verzeichnis, in dem sich Ihr python -Skript befindet.
dh:
ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py
python erstellt /absolute/path/to/script/module.pyc
und aktualisiert es, wenn Sie den Inhalt von /absolute/path/to/module/module.py
ändern.
fügen Sie dann Folgendes in mypythonscript.py ein
from module import *
Ich habe ein Paket erstellt, das imp
für Sie verwendet. Ich nenne es import_file
und so wird es verwendet:
>>>from import_file import import_file
>>>mylib = import_file('c:\\mylib.py')
>>>another = import_file('relative_subdir/another.py')
Sie können es bekommen bei:
http://pypi.python.org/pypi/import_file
oder bei
ganz einfach: Angenommen, Sie möchten eine Importdatei mit einem relativen Pfad ../../MyLibs/pyfunc.py
libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
Aber wenn Sie es ohne Wache schaffen, können Sie endlich einen sehr langen Weg zurücklegen
Eine einfache Lösung mit importlib
anstelle des imp
-Pakets (getestet für Python 2.7, obwohl es auch für Python 3 funktionieren sollte):
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")
Jetzt können Sie den Namespace des importierten Moduls direkt wie folgt verwenden:
a = module.myvar
b = module.myfunc(a)
Der Vorteil dieser Lösung ist, dass wir müssen nicht einmal den tatsächlichen Namen des Moduls kennen, das wir importieren möchten, um es in unserem Code zu verwenden. Dies ist nützlich, z.B. falls der Pfad des Moduls ein konfigurierbares Argument ist.
Dies zur Liste der Antworten hinzufügen, da ich nichts gefunden habe, was funktioniert hat. Dies ermöglicht den Import von kompilierten (pyd) python Modulen in 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()
Diese Antwort ist eine Ergänzung zu Sebastian Rittaus Antwort auf den Kommentar: "Aber was ist, wenn Sie den Modulnamen nicht haben?" Dies ist eine schnelle und unsaubere Methode, um den wahrscheinlichen python - Modulnamen mit einem Dateinamen zu ermitteln. Sie durchsucht den Baum nur, bis ein Verzeichnis ohne __init__.py
-Datei gefunden wird, und wandelt es dann wieder in ein Dateiname. Für Python 3.4+ (verwendet pathlib) ist dies sinnvoll, da Py2-Benutzer "imp" oder andere Methoden zum Ausführen relativer Importe verwenden können:
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))
Es gibt sicherlich Verbesserungsmöglichkeiten, und die optionalen __init__.py
-Dateien erfordern möglicherweise andere Änderungen, aber wenn Sie __init__.py
im Allgemeinen haben, ist dies der Trick.