一个人如何在python中处理多个模块/软件包?

时间:2018-08-09 23:21:35

标签: python import module package

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

我正在构建一个python程序,该程序可以让我在战舰游戏中将两个ais相互对抗。

这是我的目录结构:

.
├── ais_play_battleship
│   ├── game.py
│   ├── __init__.py
│   ├── player.py
│   └── ship.py
├── LICENSE
├── README.md
└── tests
    └── ship_test.py

2 directories, 7 files

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

以下是我的研究告诉我有关我的问题的信息:

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

这是我的具体问题:

  • 为什么该错误是“ ModuleNotFound”错误?应该不是“ PackageNotFound”吗?
  • 我可以将ais_play_battleship打包吗?
  • 如何将测试保存在单独的目录中,并仍然使用ais_play_battleship中的代码?

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

3 个答案:

答案 0 :(得分:1)

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

在顶级目录中:

setup.py

from setuptools import setup

setup(name='ais_play_battleship')

tox.ini

[tox]
envlist = py36, py37

[testenv]
deps=pytest
commands=
    pip install . --quiet
py.test -q

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

答案 1 :(得分:0)

我正在回答自己的问题,因为我尚未收到满意的答复。我发现的最佳资源是available here。总结:

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

  1. 将打包的模块安装在站点程序包中(这需要创建setup.py文件并使用pip install .进行安装,更多信息是available here.
  2. 修改路径以解析模块

出于下面讨论的原因,我最终选择了第二种方法。

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

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

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

然后,在我的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)

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

答案 2 :(得分:0)

tests/ship_test.py 作为模块运行

python -m tests.ship_test