Bagaimana saya bisa memuat modul Python diberikan path lengkapnya? Perhatikan bahwa file tersebut dapat berada di mana saja di sistem file, karena ini merupakan opsi konfigurasi.
Bagaimana saya bisa memuat modul Python diberikan path lengkapnya? Perhatikan bahwa file tersebut dapat berada di mana saja di sistem file, karena ini merupakan opsi konfigurasi.
Jawaban:
Untuk penggunaan Python 3.5+:
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()
Untuk Python 3.3 dan 3.4 gunakan:
from importlib.machinery import SourceFileLoader
foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()
(Meskipun ini sudah usang dalam Python 3.4.)
Untuk Python 2 gunakan:
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
Ada fungsi kenyamanan yang setara untuk file Python dan DLL yang dikompilasi.
Lihat juga http://bugs.python.org/issue21436 .
__import__
.
imp.load_source
hanya menetapkan .__name__
modul yang dikembalikan. itu tidak mempengaruhi pemuatan.
imp.load_source()
menentukan kunci entri baru yang dibuat dalam sys.modules
kamus, sehingga argumen pertama memang mempengaruhi pemuatan.
imp
modul ditinggalkan sejak versi 3.4: The imp
paket tertunda bantahan mendukung importlib
.
Keuntungan menambahkan path ke sys.path (lebih dari menggunakan imp) adalah bahwa hal itu menyederhanakan hal-hal ketika mengimpor lebih dari satu modul dari satu paket. Sebagai contoh:
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
untuk menunjuk ke file python tunggal, bukan direktori?
importlib.import_module(mod_name)
dapat digunakan sebagai pengganti impor eksplisit di sini jika nama modul tidak dikenal saat runtime saya akan menambahkan sys.path.pop()
pada akhirnya, meskipun, dengan asumsi kode yang diimpor tidak mencoba untuk mengimpor lebih banyak modul seperti yang digunakan.
Jika modul tingkat atas Anda bukan file tetapi dikemas sebagai direktori dengan __init__.py, maka solusi yang diterima hampir berfungsi, tetapi tidak cukup. Dalam Python 3.5+ kode berikut diperlukan (perhatikan baris yang ditambahkan yang dimulai dengan '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)
Tanpa baris ini, ketika exec_module dijalankan, ia mencoba untuk mengikat impor relatif di __init__.py tingkat atas ke nama modul tingkat atas - dalam hal ini "mymodule". Tetapi "mymodule" belum dimuat sehingga Anda akan mendapatkan kesalahan "SystemError: Modul induk 'mymodule' tidak dimuat, tidak dapat melakukan impor relatif". Jadi, Anda harus mengikat nama sebelum memuatnya. Alasan untuk ini adalah invarian mendasar dari sistem impor relatif: "holding invarian adalah bahwa jika Anda memiliki sys.modules ['spam'] dan sys.modules ['spam.foo'] (seperti yang Anda lakukan setelah impor di atas ), yang terakhir harus muncul sebagai atribut foo dari yang sebelumnya " seperti yang dibahas di sini .
mymodule
?
/path/to/your/module/
sebenarnya /path/to/your/PACKAGE/
? dan mymodule
maksud Anda myfile.py
?
Untuk mengimpor modul Anda, Anda perlu menambahkan direktori ke variabel lingkungan, baik sementara atau permanen.
import sys
sys.path.append("/path/to/my/modules/")
import my_module
Menambahkan baris berikut ke .bashrc
file Anda (di linux) dan jalankan source ~/.bashrc
di terminal:
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
Credit / Source: saarrrr , pertanyaan lain tentang stackexchange
Sepertinya Anda tidak ingin mengimpor file konfigurasi secara khusus (yang memiliki banyak efek samping dan komplikasi tambahan), Anda hanya ingin menjalankannya, dan dapat mengakses namespace yang dihasilkan. Pustaka standar menyediakan API khusus untuk itu dalam bentuk runpy.run_path :
from runpy import run_path
settings = run_path("/path/to/file.py")
Antarmuka itu tersedia dalam Python 2.7 dan Python 3.2+
result[name]
, result.get('name', default_value)
, dll)
from runpy import run_path; from argparse import Namespace; mod = Namespace(**run_path('path/to/file.py'))
Anda juga dapat melakukan sesuatu seperti ini dan menambahkan direktori tempat file konfigurasi berada di jalur memuat Python, dan kemudian hanya melakukan impor normal, dengan asumsi Anda tahu nama file di muka, dalam hal ini "config".
Berantakan, tetapi berhasil.
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:
klausa catch-all jarang merupakan ide yang bagus.
save_cwd = os.getcwd()
try: …
finally: os.chdir(save_cwd)
this is already addressed by the standard library
ya, tapi python memiliki kebiasaan buruk untuk tidak kompatibel ke belakang ... karena jawaban yang dicentang mengatakan ada 2 cara berbeda sebelum dan sesudah 3.3. Dalam hal ini saya lebih suka menulis fungsi universal saya sendiri daripada memeriksa versi dengan cepat. Dan ya, mungkin kode ini tidak terlindungi dengan baik dari kesalahan, tetapi ini menunjukkan sebuah ide (yaitu os.chdir (), saya belum memikirkannya), berdasarkan mana saya dapat menulis kode yang lebih baik. Karenanya +1.
Berikut adalah beberapa kode yang berfungsi di semua versi Python, dari 2.7-3.5 dan bahkan mungkin yang lain.
config_file = "/tmp/config.py"
with open(config_file) as f:
code = compile(f.read(), config_file, 'exec')
exec(code, globals(), locals())
Saya mengujinya. Mungkin jelek tapi sejauh ini adalah satu-satunya yang berfungsi di semua versi.
load_source
tidak karena mengimpor skrip dan memberikan akses skrip ke modul dan global pada saat mengimpor.
Saya telah datang dengan versi yang sedikit dimodifikasi dari jawaban luar biasa @ SebastianRittau (untuk Python> 3,4 saya pikir), yang akan memungkinkan Anda untuk memuat file dengan ekstensi apa pun sebagai modul menggunakan spec_from_loader
alih-alih 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)
Keuntungan dari pengkodean jalur secara eksplisit SourceFileLoader
adalah bahwa mesin tidak akan mencoba mencari tahu jenis file dari ekstensi. Ini berarti bahwa Anda dapat memuat sesuatu seperti .txt
file menggunakan metode ini, tetapi Anda tidak dapat melakukannya spec_from_file_location
tanpa menentukan loader karena .txt
tidak ada importlib.machinery.SOURCE_SUFFIXES
.
Apakah maksud Anda memuat atau mengimpor?
Anda dapat memanipulasi sys.path
daftar menentukan jalur ke modul Anda, lalu mengimpor modul Anda. Misalnya, diberikan modul di:
/foo/bar.py
Anda bisa melakukannya:
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.
Jadi mengapa tidak sys.path.insert(0, ...)
bukan sys.path[0:0]
?
Saya yakin Anda bisa menggunakan imp.find_module()
dan imp.load_module()
memuat modul yang ditentukan. Anda harus memisahkan nama modul dari jalur, yaitu jika Anda ingin memuat, /home/mypath/mymodule.py
Anda harus melakukan:
imp.find_module('mymodule', '/home/mypath/')
... tapi itu harus menyelesaikan pekerjaan.
Anda dapat menggunakan pkgutil
modul (khususnya walk_packages
metode) untuk mendapatkan daftar paket di direktori saat ini. Dari sana sepele untuk menggunakan importlib
mesin untuk mengimpor modul yang Anda inginkan:
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!
Buat python module test.py
import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3
Buat modul python test_check.py
from test import Client1
from test import Client2
from test import test3
Kita dapat mengimpor modul yang diimpor dari modul.
Area Python 3.4 ini tampaknya sangat berliku untuk dipahami! Namun dengan sedikit peretasan menggunakan kode dari Chris Calloway sebagai permulaan saya berhasil membuat sesuatu bekerja. Inilah fungsi dasarnya.
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
Ini tampaknya menggunakan modul yang tidak usang dari Python 3.4. Saya tidak berpura-pura mengerti mengapa, tetapi tampaknya berhasil dari dalam suatu program. Saya menemukan solusi Chris bekerja pada baris perintah tetapi tidak dari dalam suatu program.
Saya tidak mengatakan bahwa itu lebih baik, tetapi demi kelengkapan, saya ingin menyarankan exec
fungsi tersebut, tersedia dalam python 2 dan 3.
exec
memungkinkan Anda untuk mengeksekusi kode arbitrer baik dalam lingkup global, atau dalam lingkup internal, disediakan sebagai kamus.
Misalnya, jika Anda memiliki modul yang disimpan di "/path/to/module
"dengan fungsi foo()
, Anda bisa menjalankannya dengan melakukan hal berikut:
module = dict()
with open("/path/to/module") as f:
exec(f.read(), module)
module['foo']()
Ini membuatnya sedikit lebih eksplisit bahwa Anda memuat kode secara dinamis, dan memberi Anda kekuatan tambahan, seperti kemampuan untuk menyediakan builtin khusus.
Dan jika memiliki akses melalui atribut, alih-alih kunci penting bagi Anda, Anda dapat mendesain kelas dict khusus untuk global, yang menyediakan akses seperti itu, misalnya:
class MyModuleClass(dict):
def __getattr__(self, name):
return self.__getitem__(name)
Untuk mengimpor modul dari nama file yang diberikan, Anda dapat memperpanjang sementara jalur, dan mengembalikan jalur sistem di referensi blok akhirnya :
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
Jika kami memiliki skrip dalam proyek yang sama tetapi dengan cara direktori yang berbeda, kami dapat menyelesaikan masalah ini dengan metode berikut.
Dalam situasi utils.py
ini ada disrc/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
Ini seharusnya bekerja
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))
. Metode Anda berfungsi karena batasan sebelumnya untuk ekstensi .py. Juga, Anda mungkin harus mengimpor modul ke beberapa entri variabel / kamus.
Saya membuat paket yang digunakan imp
untuk Anda. Saya menyebutnya import_file
dan ini adalah bagaimana ini digunakan:
>>>from import_file import import_file
>>>mylib = import_file('c:\\mylib.py')
>>>another = import_file('relative_subdir/another.py')
Anda bisa mendapatkannya di:
http://pypi.python.org/pypi/import_file
atau di
Impor modul paket saat runtime (resep 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)
Di Linux, menambahkan tautan simbolik di direktori skrip python Anda berfungsi.
yaitu:
ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py
python akan membuat /absolute/path/to/script/module.pyc
dan akan memperbaruinya jika Anda mengubah konten/absolute/path/to/module/module.py
kemudian sertakan yang berikut ini di mypythonscript.py
from module import *
git
dan memeriksa Anda git status
untuk memverifikasi bahwa perubahan Anda pada skrip benar-benar membuatnya kembali ke dokumen sumber dan tidak tersesat di eter.
Saya telah menulis fungsi impor global dan portabel saya sendiri, berdasarkan importlib
modul, untuk:
sys.path
atau pada penyimpanan jalur pencarian apa pun.Struktur direktori contoh:
<root>
|
+- test.py
|
+- testlib.py
|
+- /std1
| |
| +- testlib.std1.py
|
+- /std2
| |
| +- testlib.std2.py
|
+- /std3
|
+- testlib.std3.py
Ketergantungan dan keteraturan inklusi:
test.py
-> testlib.py
-> testlib.std1.py
-> testlib.std2.py
-> testlib.std3.py
Penerapan:
Toko perubahan terbaru: 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')
Output ( 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
Diuji di Python 3.7.4
, 3.2.5
,2.7.16
Pro :
testlib.std.py
seperti testlib
, testlib.blabla.py
sepertitestlib_blabla
dan seterusnya).sys.path
atau pada penyimpanan jalur pencarian apa pun.SOURCE_FILE
dan SOURCE_DIR
antar panggilan ketkl_import_module
.3.4.x
dan lebih tinggi] Dapat mencampur ruang nama modul dalam tkl_import_module
panggilan bersarang (mis: named->local->named
ataulocal->named->local
dan sebagainya).3.4.x
dan lebih tinggi] Dapat mengekspor variabel / fungsi / kelas global secara otomatis dari tempat dideklarasikan ke semua modul anak yang diimpor melalui tkl_import_module
(melalui tkl_declare_global
fungsi).Cons :
3.3.x
dan lebih rendah] Harus menyatakan tkl_import_module
dalam semua modul yang membutuhkan tkl_import_module
(duplikasi kode)Perbarui 1,2 (untuk3.4.x
dan lebih tinggi):
Dalam Python 3.4 dan lebih tinggi Anda dapat melewati persyaratan untuk mendeklarasikan tkl_import_module
dalam setiap modul dengan mendeklarasikantkl_import_module
dalam modul tingkat atas dan fungsinya akan menyuntikkan dirinya sendiri ke semua modul anak-anak dalam satu panggilan (ini semacam impor self deploy).
Perbarui 3 :
Menambahkan fungsi tkl_source_module
sebagai analog ke bash source
dengan penjaga eksekusi dukungan saat impor (diimplementasikan melalui penggabungan modul, bukan impor).
Pembaruan 4 :
Fungsi yang ditambahkan tkl_declare_global
untuk secara otomatis mengekspor variabel global modul ke semua modul anak-anak di mana variabel global modul tidak terlihat karena bukan merupakan bagian dari modul anak.
Pembaruan 5 :
Semua fungsi telah pindah ke perpustakaan tacklelib, lihat tautan di atas.
Ada paket yang didedikasikan untuk ini secara khusus:
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')
Ini diuji di versi Python (Jython dan PyPy juga), tetapi mungkin berlebihan tergantung pada ukuran proyek Anda.
Menambahkan ini ke daftar jawaban karena saya tidak dapat menemukan apa pun yang berfungsi. Ini akan memungkinkan impor modul python dikompilasi (pyd) di 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()
caranya cukup sederhana: misalkan Anda ingin mengimpor file dengan path relatif ../../MyLibs/pyfunc.py
libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
Tetapi jika Anda berhasil tanpa penjaga Anda akhirnya bisa mendapatkan jalan yang sangat panjang
Solusi sederhana menggunakan importlib
alih-alih imp
paket (diuji untuk Python 2.7, meskipun harus bekerja untuk Python 3 juga):
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")
Sekarang Anda dapat langsung menggunakan namespace dari modul yang diimpor, seperti ini:
a = module.myvar
b = module.myfunc(a)
Keuntungan dari solusi ini adalah kita bahkan tidak perlu tahu nama sebenarnya dari modul yang ingin kita impor , untuk menggunakannya dalam kode kita. Ini berguna, misalnya jika jalur modul adalah argumen yang dapat dikonfigurasi.
sys.path
, yang tidak cocok untuk setiap kasus penggunaan.
sys.path.pop()
Jawaban ini adalah tambahan untuk jawaban Sebastian Rittau menanggapi komentar: "tetapi bagaimana jika Anda tidak memiliki nama modul?" Ini adalah cara cepat dan kotor untuk mendapatkan nama modul python yang mungkin diberikan nama file - hanya naik pohon sampai menemukan direktori tanpa __init__.py
file dan kemudian mengubahnya kembali menjadi nama file. Untuk Python 3.4+ (menggunakan pathlib), yang masuk akal karena orang Py2 dapat menggunakan "imp" atau cara lain untuk melakukan impor relatif:
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))
Tentunya ada kemungkinan untuk peningkatan, dan __init__.py
file-file opsional mungkin memerlukan perubahan lain, tetapi jika Anda memiliki __init__.py
secara umum, ini adalah triknya.
Cara terbaik, saya pikir, adalah dari dokumentasi resmi ( 29.1. Imp - Akses internal impor ):
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()