Tam yolu verilen bir Python modülünü nasıl yükleyebilirim? Bir yapılandırma seçeneği olduğundan dosyanın dosya sisteminin herhangi bir yerinde olabileceğini unutmayın.
Tam yolu verilen bir Python modülünü nasıl yükleyebilirim? Bir yapılandırma seçeneği olduğundan dosyanın dosya sisteminin herhangi bir yerinde olabileceğini unutmayın.
Yanıtlar:
Python 3.5+ kullanımı için:
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()
Python 3.3 ve 3.4 için:
from importlib.machinery import SourceFileLoader
foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()
(Bu Python 3.4'te kullanımdan kaldırılmasına rağmen.)
Python 2 için:
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
Derlenmiş Python dosyaları ve DLL dosyaları için eşdeğer kolaylık işlevleri vardır.
Ayrıca bkz . Http://bugs.python.org/issue21436 .
__import__
.
imp.load_source
yalnızca .__name__
döndürülen modülün ilk argümanının değerini ayarlar . yüklemeyi etkilemez.
imp.load_source()
oluşturulan yeni girdinin anahtarını belirler sys.modules
, bu nedenle ilk argüman yüklemeyi gerçekten etkiler.
imp
Modül sürümü 3.4 beri kullanım dışı kalmıştır: imp
paket lehine itirazın bekliyor importlib
.
Sys.path (imp kullanarak aşırı) yolu eklemenin avantajı, tek bir paketten birden fazla modül içe aktarırken işleri basitleştirmesidir. Örneğin:
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
Dizin yerine tek bir python dosyasına işaret etmek için nasıl kullanılır ?
importlib.import_module(mod_name)
modül adı çalışma zamanında bilinmiyorsa, burada açık içe aktarma yerine kullanılabilir sys.path.pop()
, ancak sonunda, içe aktarılan kodun kullanıldıkça daha fazla modül içe aktarmaya çalışmadığı varsayılarak ekleyeceğim .
Üst düzey modülünüz bir dosya değilse ancak __init__.py ile bir dizin olarak paketlenmişse, kabul edilen çözüm neredeyse çalışır, ancak tam olarak çalışmaz. Python 3.5+ sürümünde aşağıdaki kod gereklidir ('sys.modules' ile başlayan ek satırı not edin):
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)
Bu satır olmadan, exec_module yürütüldüğünde, üst düzey __init__.py'deki göreli içe aktarımları üst düzey modül adına bağlamaya çalışır - bu durumda "mymodule". Ancak "mymodule" henüz yüklenmediği için "SystemError: 'mymodule' ana modülü yüklenmedi, göreli içe aktarma gerçekleştirilemiyor" hatasını alırsınız. Bu yüzden yüklemeden önce adı bağlamanız gerekir. Bunun nedeni, göreli ithalat sisteminin temel değişmezidir: "Değişmez tutma, sys.modules ['spam'] ve sys.modules ['spam.foo'] (yukarıdaki içe aktarmadan sonra yaptığınız gibi) ), ikincisinin " burada tartışıldığı gibi " ilkinin foo özelliği olarak görünmesi gerekir .
mymodule
?
/path/to/your/module/
aslında /path/to/your/PACKAGE/
? ve mymodule
ne demek istiyorsun myfile.py
?
Modülünüzü içe aktarmak için, dizinini geçici veya kalıcı olarak ortam değişkenine eklemeniz gerekir.
import sys
sys.path.append("/path/to/my/modules/")
import my_module
.bashrc
Dosyanıza (linux cinsinden) aşağıdaki satırı ekleme ve source ~/.bashrc
terminalde excecute :
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
Kredi / Kaynak: saarrrr , başka bir yığın değişim sorusu
Yapılandırma dosyasını (çok fazla yan etkisi ve ek komplikasyonları olan) içe aktarmak istemediğiniz, sadece çalıştırmak istediğiniz ve sonuçta elde edilen ad alanına erişebildiğiniz anlaşılıyor. Standart kütüphane, runpy.run_path biçiminde özel bir API sağlar :
from runpy import run_path
settings = run_path("/path/to/file.py")
Bu arayüz Python 2.7 ve Python 3.2+ sürümlerinde mevcuttur
result[name]
, result.get('name', default_value)
vs)
from runpy import run_path; from argparse import Namespace; mod = Namespace(**run_path('path/to/file.py'))
Bunun gibi bir şey de yapabilir ve yapılandırma dosyasının içinde bulunduğu dizini Python yükleme yoluna ekleyebilir ve daha sonra normal bir içe aktarma yaparak dosyanın adını önceden bildiğinizi varsayarak bu durumda "config" yapabilirsiniz.
Dağınık, ama işe yarıyor.
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:
şartını kullanmak nadiren iyi bir fikirdir.
save_cwd = os.getcwd()
try: …
finally: os.chdir(save_cwd)
this is already addressed by the standard library
evet, ama python geriye dönük uyumlu olmama gibi kötü bir alışkanlığa sahip ... kontrol edilen cevap 3.3'ten önce ve sonra 2 farklı yol olduğunu söylüyor. Bu durumda, versiyonunu anında kontrol etmekten ziyade kendi evrensel fonksiyonumu yazmak istiyorum. Ve evet, belki de bu kod çok iyi hata korumalı değildir, ancak daha iyi bir kod yazabileceğime dayanarak bir fikir (os.chdir (), bununla birlikte değilim) gösterir. Dolayısıyla +1.
İşte tüm Python sürümlerinde çalışan bazı kodlar, 2.7-3.5 ve muhtemelen diğerleri.
config_file = "/tmp/config.py"
with open(config_file) as f:
code = compile(f.read(), config_file, 'exec')
exec(code, globals(), locals())
Test ettim. Çirkin olabilir, ancak şimdiye kadar tüm versiyonlarda çalışan tek kişi.
load_source
yaramadı çünkü komut dosyasını içe aktardığı ve içe aktarma sırasında komut dosyasına modüllere ve globallere erişim sağladığı için işe yaramadı.
@ SebastianRittau harika cevabının biraz değiştirilmiş bir versiyonu ile geldim (Python> 3.4 için), bunun spec_from_loader
yerine kullanarak herhangi bir uzantıya sahip bir modülü modül olarak yüklemenize izin verecek 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)
Yolu açık bir şekilde kodlamanın avantajı SourceFileLoader
, makinenin uzantıdan dosyanın türünü bulmaya çalışmamasıdır. Bu, .txt
bu yöntemi kullanarak dosya gibi bir şey yükleyebileceğiniz anlamına gelir , ancak içinde spec_from_file_location
olmadığı için yükleyiciyi belirtmeden bunu .txt
yapamazsınız importlib.machinery.SOURCE_SUFFIXES
.
Yük veya ithalat mı demek istediniz?
sys.path
Modülünüzün yolunu belirten listeyi değiştirebilir , ardından modülünüzü içe aktarabilirsiniz. Örneğin, bir modül verildiğinde:
/foo/bar.py
Şunları yapabilirsiniz:
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.
Neden olmasın Yani sys.path.insert(0, ...)
yerine sys.path[0:0]
?
Belirtilen modülü kullanabileceğinizi imp.find_module()
ve imp.load_module()
yükleyebileceğinizi düşünüyorum . Modül adını yoldan ayırmanız gerekir, yani yüklemek /home/mypath/mymodule.py
istiyorsanız yapmanız gerekenler:
imp.find_module('mymodule', '/home/mypath/')
... ama bu işi halletmeli.
Geçerli dizindeki paketlerin bir listesini almak için pkgutil
modülü (özellikle walk_packages
yöntem) kullanabilirsiniz. Oradan importlib
istediğiniz modülleri almak için makineleri kullanmak önemsizdir :
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!
Python module test.py oluştur
import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3
Python modülü oluştur test_check.py
from test import Client1
from test import Client2
from test import test3
İthal modülü modülden alabiliriz.
Python 3.4'ün bu alanının anlaşılması son derece kıvrımlı görünüyor! Ancak bir başlangıç olarak Chris Calloway kodunu kullanarak kesmek biraz ile çalışan bir şey başardı. İşte temel işlev.
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
Bu, Python 3.4'teki kullanımdan kaldırılmış modülleri kullanıyor gibi görünüyor. Nedenini anlamıyormuş gibi yapmıyorum, ama bir program içinden çalışıyor gibi görünüyor. Chris'in çözümünün komut satırında çalıştığını, ancak programın içinden çalışmadığını gördüm.
Bunun iyi olduğunu söylemiyorum, fakat bütünlük uğruna, ben önermek istedik exec
hem piton 2 mevcuttur fonksiyonunu ve 3.
exec
, küresel etki ya rasgele kod yürütmesine olanak veya dahili kapsamında sözlük olarak sağlanmıştır.
Örneğin, "/path/to/module
"" işleviyle birlikte depolanmış bir modülünüz varsa foo()
, aşağıdakileri yaparak çalıştırabilirsiniz:
module = dict()
with open("/path/to/module") as f:
exec(f.read(), module)
module['foo']()
Bu, kodu dinamik olarak yüklediğinizi biraz daha açık hale getirir ve size özel yerleşikler sağlama yeteneği gibi bazı ek güç verir.
Nitelikler aracılığıyla erişime sahipseniz, anahtarlar yerine sizin için önemliyse, globaller için bu tür bir erişim sağlayan özel bir dikte sınıfı tasarlayabilirsiniz, örneğin:
class MyModuleClass(dict):
def __getattr__(self, name):
return self.__getitem__(name)
Belirli bir dosya adından bir modülü içe aktarmak için, yolu geçici olarak genişletebilir ve son olarak blok başvurusunda sistem yolunu geri yükleyebilirsiniz :
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
Bu çalışmalı
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))
. Yönteminiz, .py uzantısına yönelik önceki kısıtlama nedeniyle çalışır. Ayrıca, modülü muhtemelen bazı değişken / sözlük girişlerine aktarmanız gerekir.
Aynı projede ancak farklı dizin araçlarında komut dosyalarımız varsa, bu sorunu aşağıdaki yöntemle çözebiliriz.
Bu durum ise utils.py
içindedirsrc/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
Sizin için bir paket hazırladım imp
. Ben diyorum import_file
ve bu nasıl kullanılır:
>>>from import_file import import_file
>>>mylib = import_file('c:\\mylib.py')
>>>another = import_file('relative_subdir/another.py')
Şuradan alabilirsiniz:
http://pypi.python.org/pypi/import_file
ya da
Paket modüllerini çalışma zamanında içe aktarma (Python tarifi)
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)
Linux'ta, python betiğinizin bulunduğu dizine sembolik bir bağlantı eklemek işe yarar.
yani:
ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py
python /absolute/path/to/script/module.pyc
, içeriğini değiştirirseniz oluşturur ve günceller/absolute/path/to/module/module.py
ardından mypythonscript.py dosyasına aşağıdakileri ekleyin
from module import *
git
için kullanarak ve kontrol ederek bu sorunlardan bazılarını yakalayabilirsiniz git status
.
importlib
Modüle dayalı olarak kendi global ve taşınabilir içe aktarma işlevimi yazdım :
sys.path
arama yolu depolama alanına bağlı veya bunun yerine önceden içe aktarılan modüle göre tanımlayabilme .Örnek dizin yapısı:
<root>
|
+- test.py
|
+- testlib.py
|
+- /std1
| |
| +- testlib.std1.py
|
+- /std2
| |
| +- testlib.std2.py
|
+- /std3
|
+- testlib.std3.py
İçerme bağımlılığı ve düzeni:
test.py
-> testlib.py
-> testlib.std1.py
-> testlib.std2.py
-> testlib.std3.py
Uygulama:
Son değişiklikler mağazası: 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')
Çıktı ( 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
Python test edilmiştir 3.7.4
, 3.2.5
,2.7.16
Artıları :
testlib.std.py
olarak testlib
, testlib.blabla.py
olarak testlib_blabla
ve diğerleri).sys.path
bir arama yolu depolama alanına veya buna bağlı değildir .SOURCE_FILE
ve SOURCE_DIR
arasındaki genel değişkenlerin kaydedilmesini / geri yüklenmesini gerektirmez tkl_import_module
.3.4.x
ve daha yüksek] İç içe tkl_import_module
çağrılarda modül ad alanlarını karıştırabilir (ör: named->local->named
veyalocal->named->local
vs.).3.4.x
ve daha yüksek] Genel değişkenleri / işlevleri / sınıfları bildirildiği yerden tkl_import_module
( tkl_declare_global
işlev aracılığıyla ) alınan tüm alt modüllere otomatik olarak verebilir .Eksileri :
3.3.x
ve daha düşük] Çağrıyı yapan tkl_import_module
tüm modüllerde tkl_import_module
(kod çoğaltma)1,2 Güncellemesi (için3.4.x
yalnızca ve üstü için):
Python 3.4 ve üzeri sürümlerde , bir üst düzey modülde tkl_import_module
bildirerek her bir modülde bildirme gereksinimini atlayabilirsiniz tkl_import_module
ve işlev tek bir çağrıda tüm alt modüllere kendini enjekte eder (bu bir tür kendi kendine konuşlandırmayı içe aktarmadır).
Güncelleme 3 :
İçe aktarma sırasında destek yürütme korumasıyla tkl_source_module
bash'a analog olarak işlev eklendi source
(içe aktarma yerine modül birleştirme yoluyla uygulanır).
Güncelleme 4 :
tkl_declare_global
Bir modül genel değişkenini, alt modülün bir parçası olmadığı için modül genel değişkeninin görünmediği tüm alt modüllere otomatik olarak dışa aktarma işlevi eklendi .
Güncelleme 5 :
Tüm işlevler tacklelib kütüphanesine taşındı, yukarıdaki bağlantıya bakın.
Özellikle buna adanmış bir paket var:
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')
Python sürümlerinde (Jython ve PyPy de) test edilmiştir, ancak projenizin boyutuna bağlı olarak aşırı olabilir.
Bunu işe yarayan bir şey bulamadığım için cevap listesine ekliyorum. Bu, derlenmiş (pyd) python modüllerinin 3.4'te içe aktarılmasına izin verecektir:
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()
oldukça basit bir yol var: göreceli yolla dosya almak istediğinizi varsayalım ../../MyLibs/pyfunc.py
libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
Ama eğer bir gardiyan olmadan yaparsanız, sonunda çok uzun bir yol elde edebilirsiniz.
Paket importlib
yerine kullanarak basit bir çözüm imp
(Python 3 için de çalışmasına rağmen Python 2.7 için test edilmiştir):
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")
Şimdi içe aktarılan modülün ad alanını doğrudan kullanabilirsiniz, şöyle:
a = module.myvar
b = module.myfunc(a)
Bu çözümün avantajı , kodumuzda kullanmak için içe aktarmak istediğimiz modülün gerçek adını bile bilmemize gerek yoktur . Bu, örneğin modülün yolunun yapılandırılabilir bir argüman olması durumunda kullanışlıdır.
sys.path
, her kullanım durumuna uymayan 'ı değiştirirsiniz .
sys.path.pop()
Bu cevap Sebastian Rittau'nun şu cevaba verdiği cevaba ek niteliğindedir: "ama modül isminiz yoksa ne olacak?" Bu, bir dosya adı verilen olası python modülü adını almanın hızlı ve kirli bir yoludur - sadece dosyasız bir dizin bulana __init__.py
ve sonra tekrar bir dosya adına dönüşene kadar ağaca gider . Py2 kullanıcıları "imp" veya göreli ithalat yapmanın diğer yollarını kullanabildikleri için mantıklı olan Python 3.4+ (pathlib kullanır):
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))
Kesinlikle iyileştirme olasılıkları vardır ve isteğe bağlı __init__.py
dosyalar başka değişiklikler gerektirebilir, ancak __init__.py
genel olarak varsa, bu hile yapar.
En iyi yolu, bence, resmi belgelerden ( 29.1. İmp - İthalat içlerine erişim ):
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()