如何在 python 中处理多个模块/包?

bwe*_*r13 6 python import module package

我花了几个小时研究这个问题,但我仍然感到困惑。请发现我的无知很迷人。

我正在构建一个 python 程序,它允许我在战舰游戏中让两个 AI 相互对抗。

这是我的目录结构:

.
??? ais_play_battleship
?   ??? game.py
?   ??? __init__.py
?   ??? player.py
?   ??? ship.py
??? LICENSE
??? README.md
??? tests
    ??? ship_test.py

2 directories, 7 files
Run Code Online (Sandbox Code Playgroud)

目前,我正在尝试编写ship_test.py,但似乎无法导入ais_play_battleship.ship. 我得到了可怕的“ModuleNotFoundError”

以下是我的研究告诉我有关我的问题的内容:

  • 如果要从另一个目录导入 python 代码,则应将该目录设为包而不是模块。因此,我__init__.pyais_play_battleship.
  • Python 只会搜索 python 启动的目录以及您正在运行的脚本的目录。因此,我一直试图通过python3 tests/ship_tests.py从根目录运行来启动我的测试。

以下是我的具体问题:

  • 为什么错误是“ModuleNotFound”错误?不应该是“PackageNotFound”吗?
  • 将 ais_play_battleship 制作成包裹是否正确?
  • 如何将我的测试保存在单独的目录中并仍然使用 ais_play_battleship 中的代码?

请原谅我,因为我不太擅长在 StackOverflow 上提问。请告诉我如何改进。

bwe*_*r13 6

我正在回答我自己的问题,因为我还没有收到满意的答复。我找到的最好的资源可以在这里找到。总之:

Python 不会在您运行 Python 的目录中搜索模块。此外,添加一个__init__.py文件来使目录成为包并不足以使其对在另一个文件夹中运行的 python 实例可见。您还必须安装该软件包。因此,访问另一个目录中的模块的唯一两种方法是:

  1. 在 site-packages 中安装打包模块(这需要创建setup.py文件并使用此处提供pip install .更多信息进行安装
  2. 修改路径以解析模块

由于下面讨论的原因,我最终选择了第二个选项。

第一个选项要求在每次更改包时重新安装包。这在不断变化的代码库上很困难,但可以通过使用构建自动化变得更容易。但是,我想避免这种增加的复杂性。

我很长一段时间都回避第二个选项,因为修改路径似乎需要对我的模块的绝对路径进行硬编码,这显然是不可接受的,因为每个开发人员都必须编辑该路径以适应他们的环境。但是,本指南提供了此问题的解决方案。创建一个./tests/context.py包含以下内容的文件:

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
Run Code Online (Sandbox Code Playgroud)

然后,在我的ship_test.py模块中,我导入了上下文和我需要的模块:

import context
import ais_play_battleship.ship
# (I include the submodule ship because ais_play_battleship itself does not have
# any attributes or methods, and the submodule ship is the only one I am testing
# in ship_test.py)
Run Code Online (Sandbox Code Playgroud)

这更适合我的项目,因为它可以按预期工作,而不必担心安装我的包(或安装我的包的方法)。

  • 回复:`“第一个选项要求在每次更改包时重新安装包。这对于不断变化的代码库来说很困难,但可以通过使用构建自动化变得更容易。但是,我想避免这种添加复杂性。”` 对于开发,您可以执行所谓的“可编辑”安装:`pip install -e 。` (2认同)

Tht*_*htu 2

要解决此问题而不依赖于对您的 进行黑客攻击sys.path,请创建一个 setup.py 文件并作为测试运行程序的构建步骤,首先运行它pip install .。您可能想使用像tox.

在顶级目录中:

安装程序.py

from setuptools import setup

setup(name='ais_play_battleship')
Run Code Online (Sandbox Code Playgroud)

毒物文件

[tox]
envlist = py36, py37

[testenv]
deps=pytest
commands=
    pip install . --quiet
py.test -q
Run Code Online (Sandbox Code Playgroud)

然后运行您的测试(在本示例中,我们使用 tox 来执行此操作,以便我们还可以配置如何配置测试环境):tox