从文件夹动态导入所有模块

Importing dynamically all modules from a folder

我知道有 this question,但它们不仅不起作用,而且也不是我想要的。我正在开发一款赛车游戏,想从一个文件夹中动态加载所有曲目(它们存储为 .py 而不是 .json)。我不想知道曲目名称,因为用户可以随意mod/add。我只想导入他们的数据。所以,例如:

>tracks 
>>track0.py
>>track1.py
>>track2.py
>>track3.py
>>track4.py

在每个轨道中,我有这样的数据:

track_ground_data = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1],
    [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1],
    [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1],
    [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]

我需要像这样导入每个轨道模块:

loaded_tracks = [t for t in tracks] # Where tracks is the folder.

然后像这样访问给定的 track_ground_data

loaded_tracks[0].track_ground_data

如果我知道 Python 对其导入如此苛刻,我会使用 json 而不是 .py。

Python 不会 自动导入包中包含的子模块。 因此 import tracks 加载 tracks/__init__.py.

但是您可以将代码放入 __init__.py 文件中,该文件导入它在该目录中找到的所有模块。

例如在 __init__.py:

中放入这样的内容
import os
import importlib

__globals = globals()

for file in os.listdir(os.path.dirname(__file__)):
    mod_name = file[:-3]   # strip .py at the end
    __globals[mod_name] = importlib.import_module('.' + mod_name, package=__name__)

当仅导入 tracks.

时,应该使您的子模块可用 tracks.trackX

或者您可以使用 exec:

import os
import importlib

for file in os.listdir(os.path.dirname(__file__)):
    mod_name = file[:-3]   # strip .py at the end
    exec('import .' + mod_name)

更简洁的方法是使用导入挂钩或实现您自己的自定义模块导入器。使用 importlib see also sys.path_hooks

有多种方法可以做到这一点

当框架有插件或附加系统供社区贡献时,通常会面临动态导入模块的问题。每个插件或附加组件都是一个模块,包含 类 和符合框架架构和 api.

的功能

考虑到这一点,"joining the dots" 框架代码和任意多个附加组件之间的解决方案是通过 python 标准库中的 importlib。你似乎面临同样的结构性问题。

这是一个用 importlib 回答的计算器 question。 还有 documentation.

为了未来的 pythoners 的福祉,我发布了我是如何解决的。一个朋友帮我解决了。无法使 Bakuriu 的解决方案起作用,因为模块是空的。在 __init__.py 里面我放了:

import os

dir = os.path.dirname(os.path.abspath(__file__))
modules = [os.path.splitext(_file)[0] for _file in os.listdir(dir) if not _file.startswith('__')]

tracks = []
for mod in modules:
    exec('from tracks import {}; tracks.append({})'.format(mod, mod))

然后,在主文件中,我将其加载为:

dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(dir)

from tracks import tracks

然后:

loaded_tracks = [t for t in tracks]

其实很好解决的。我几乎要切换到 JSON / 放弃。