我遇到的情况是,在我的 Python 3 项目中,在运行时必须包含某些模块。我在用着importlib.import_module
为了这。
第二次更新:我确实找到了一种方法来做一些接近我想要的事情。一些额外的代码可能会使我的一些链接稍微偏离一些。我将发布一个答案来展示我做了什么。
第一次更新:通过各种 Python 小组,我被告知这是不可能的。我在底部有一个更新部分。
设置
这个想法是,当用户运行我的脚本时,将搜索任何名为“agents_*.py”的文件(其中 * 被某个单词替换)以查找类并导入这些类。例如,一个名为agents_human.py
将有一个名为HumanAgent
。就是那个HumanAgent
将被实例化的类,这就是为什么我需要导入模块(文件)以便发生这种情况。
基本问题
这个问题有两个方面:
- 我似乎无法让这个模块在多个目录中查找。
- 当我的程序安装时,导入模块根本不起作用。
问题背景
我有一个代码库显示了我正在尝试做的事情:https://github.com/jeffnyman/pacumen https://github.com/jeffnyman/pacumen
问题在于加载代理() https://github.com/jeffnyman/pacumen/blob/master/pacumen/__main__.py#L110方法;具体来说这个说法 https://github.com/jeffnyman/pacumen/blob/master/pacumen/__main__.py#L132.
为了说明这一点,如果您克隆该存储库,则可以从项目根目录运行以下命令:
python3 -m pacumen
- That 将工作 if the
agents_human.py
文件位于项目的根目录中。
- It will not工作,如果
agents_human.py
文件是一个agents
项目内的目录。
在我的代码仓库中,agents_human.py
文件位于agents
目录,因此导入失败。但如果该文件被移动到根目录,您会看到导入有效。然而,正如在load_agent()
函数中,我已将当前工作目录加上“agents”目录添加到路径中(第 119 - 121 行 https://github.com/jeffnyman/pacumen/blob/master/pacumen/__main__.py#L119)
当我说导入失败时,我的意思是:当调用导入逻辑时,the ImportError例外 https://github.com/jeffnyman/pacumen/blob/master/pacumen/__main__.py#L133被触发。再次强调,这仅当agents_human.py
文件位于agents
目录。
待解决的问题
理想情况下,我希望这适用于两种方法:当文件位于根目录中时以及当文件位于agents
目录。
其他问题背景
我只是打算忍受必须将文件放在根目录中。但是,更糟糕的是,当安装程序(而不是从项目根目录运行)时,即使上面有效的部分也不再有效。
具体来说,从克隆项目的项目根目录中,我执行以下操作:
pip3 install .
然后我创建一些目录(比如说,test_pacumen
)。在那里我放了一个agents_human.py
文件的唯一内容是:
class HumanAgent:
pass
(还需要的是layouts
我的项目目录。)
然后我运行:
pacumen
在这种情况下,逻辑永远不会导入agents_human.py
文件...即使它位于执行命令的根目录中。
我尝试过什么
通过查看各种示例,我的理解是我必须通过相对名称或提供显式锚点进行导入。但这似乎是通过提供在其中搜索模块的路径来实现的。我上面链接的代码似乎就是这样做的。
我得到了在路径上找到的模块名称(通过这条线 https://github.com/jeffnyman/pacumen/blob/master/pacumen/__main__.py#L128)并且在所有情况下,它都会找到我放置的相关文件。所以看起来路径正在工作;不是导入。这就是我找不到很多指导的地方。
我还尝试以这种方式获取每个文件路径的路径结尾部分:
module_end_dir = os.path.basename(os.path.normpath(module_dir))
然后,有了这个,我尝试了这个:
agent_module = importlib.import_module(f"{module_end_dir}.{module_name[:-3]}")
这在本地有效agents_human.py
在里面agents
目录,但如果agents_human.py
是在根部。而且当程序安装后仍然根本不起作用。
问题总结
在第一个问题上下文(未安装的上下文)中,我不知道为什么agents_human.py
模块无法导入agents
但可以从根导入。
在第二个上下文(已安装)中,似乎agents_human.py
即使模块位于根目录中,也无法导入。
我希望我在这里提供的内容不会太令人困惑。
UPDATE:
我得到了为我的孩子尝试这样的想法load_agent
功能:
def load_agent(pacman, not_human):
module = importlib.import_module("agents.agents_human")
return getattr(module, pacman)
当程序通过其项目根运行时,这确实有效,但当项目通过 pip 安装时,这不起作用。显然,这与脚本的入口点以及 Python 如何无法将目录识别为该上下文中的模块有关。
提供了我想到的另一个例子:
def load_agent(pacman, not_human):
import re
pysearchre = re.compile('.py$', re.IGNORECASE)
agent_files = filter(pysearchre.search, os.listdir(os.path.join(os.getcwd(), 'agents')))
form_module = lambda fp: '.' + os.path.splitext(fp)[0]
agents = map(form_module, agent_files)
importlib.import_module('agents')
for agent in agents:
if not agent.startswith('__'):
agent_module = importlib.import_module(agent, package="agents")
if pacman in dir(agent_module):
return getattr(agent_module, pacman)
raise Exception("The agent " + pacman + " is not specified in any agents_*.py file.")
同样的情况。无需安装即可运行该程序;安装程序时不会。
这基本上是为了确认当通过 pip 安装 Python 程序时我想做的事情是不可能的。我不是entirely深信不疑,但我包含此更新以防其他人遇到此情况。