2 回答

TA貢獻(xiàn)1815條經(jīng)驗(yàn) 獲得超13個(gè)贊
您的問題分為兩個(gè)步驟(從我的角度來看):
瀏覽您的目錄和子目錄并找到您要導(dǎo)入的所有 .py 文件的名稱
導(dǎo)入它們!
為了解決(1),我們可以使用os.walk
方法找到所有的 .py 文件。這個(gè)函數(shù)看起來像這樣:
import os
def get_py_files(src):
cwd = os.getcwd() # Current Working directory
py_files = []
for root, dirs, files in os.walk(src):
for file in files:
if file.endswith(".py"):
py_files.append(os.path.join(cwd, root, file))
return py_files
現(xiàn)在您已經(jīng)有了 .py 文件的列表,我們需要一個(gè)可以動(dòng)態(tài)導(dǎo)入它們的函數(shù)。
import importlib
def dynamic_import(module_name, py_path):
module_spec = importlib.util.spec_from_file_location(module_name, py_path)
module = importlib.util.module_from_spec(module_spec)
module_spec.loader.exec_module(module)
return module
現(xiàn)在我們只需要將它們放在一起,編寫一個(gè)調(diào)用你的get_py_files函數(shù)然后循環(huán)結(jié)果的函數(shù),用dynamic_import.
我假設(shè)您希望您在 python 腳本中使用的模塊名稱與文件名相同,但是您可以通過修改module_name下面函數(shù)中的變量來更改它。
def dynamic_import_from_src(src, star_import = False):
my_py_files = get_py_files(src)
for py_file in my_py_files:
module_name = os.path.split(py_file)[-1].strip(".py")
imported_module = dynamic_import(module_name, py_file)
if star_import:
for obj in dir(imported_module):
globals()[obj] = imported_module.__dict__[obj]
else:
globals()[module_name] = imported_module
return
請(qǐng)注意,我們必須調(diào)用globals()將模塊添加到全局命名空間。如果不這樣做,模塊將被導(dǎo)入,但您將無法訪問其中的任何內(nèi)容。如果您希望它是星形導(dǎo)入,則可以傳遞star_import = True給。dynamic_import_from_src(如. 請(qǐng)注意,這可能會(huì)覆蓋命名空間中的變量,但這是使用導(dǎo)入from first.foo import *的缺點(diǎn)之一。*
將它們?nèi)糠旁谝粋€(gè)塊中,這樣更容易一次看到它們:
import os
import importlib
def get_py_files(src):
cwd = os.getcwd() # Current Working directory
py_files = []
for root, dirs, files in os.walk(src):
for file in files:
if file.endswith(".py"):
py_files.append(os.path.join(cwd, root, file))
return py_files
def dynamic_import(module_name, py_path):
module_spec = importlib.util.spec_from_file_location(module_name, py_path)
module = importlib.util.module_from_spec(module_spec)
module_spec.loader.exec_module(module)
return module
def dynamic_import_from_src(src, star_import = False):
my_py_files = get_py_files(src)
for py_file in my_py_files:
module_name = os.path.split(py_file)[-1].strip(".py")
imported_module = dynamic_import(module_name, py_file)
if star_import:
for obj in dir(imported_module):
globals()[obj] = imported_module.__dict__[obj]
else:
globals()[module_name] = imported_module
return
if __name__ == "__main__":
dynamic_import_from_src("first", star_import = False)
此時(shí),您可以訪問您導(dǎo)入的任何模塊,就像您使用import first.whatever. 例如,如果first/numbers/one.py包含x=1,那么您可以通過說 來訪問它one.x。

TA貢獻(xiàn)1825條經(jīng)驗(yàn) 獲得超6個(gè)贊
我自己一直在修補(bǔ)這個(gè)問題,我想我已經(jīng)找到了另一種方法。我相信我自己的解決方案或@SyntaxVoid 的解決方案都應(yīng)該有效。
from importlib import util
from os import path
from glob import glob
def import_submodules(start_path, include_start_directory=True):
start_path = path.abspath(start_path)
pattern = '**/*.py' if include_start_directory else '*/**/*.py'
py_files = [f for f in glob(path.join(start_path, pattern), recursive=True) if not f.endswith('__.py')]
for py_file in py_files:
spec = util.spec_from_file_location('', py_file)
module = util.module_from_spec(spec)
spec.loader.exec_module(module)
添加回答
舉報(bào)