使用setup.py安装包时的导入错误
我在用 setup.py
来设置一个 Python 包的时候遇到了一些问题。首先,我的项目目录结构是这样的:
maindir
|- setup.py
|-mymodule
|- __init__.py
|- mainmodule.py
|-subdir
|- __init__.py
|- submodule.py
也就是说,项目目录里有一个 setup.py
文件,还有一个叫 mymodule
的文件夹,里面又有两个 Python 模块,分别在两个不同的文件夹里。
文件 submodule.py
里只包含:
teststring = "hello world"
mainmodule.py
里包含:
from .subdir import submodule
mainstring = "42"
而 setup.py
里包含:
import os
from setuptools import setup
setup(
name = "mytestmodule",
version = "0.0.1",
description = ("A simple module."),
packages=['mymodule'],
)
当我在 sourceTest
目录里用 ipython
执行 from mymodule import mainmodule
时,一切都正常,我可以引用比如 mainmodule.submodule.teststring
,这会给我返回字符串 hello world
。
但是,当我用 python setup.py install
安装这个“包”,然后在其他目录里尝试同样的操作时,我却遇到了导入错误:
In [1]: from mymodule import mainmodule
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
/home/alexander/<ipython-input-1-cf4c9bafa487> in <module>()
----> 1 from mymodule import mainmodule
/home/alexander/build/bdist.linux-i686/egg/mymodule/mainmodule.py in <module>()
ImportError: No module named subdir
我不知道自己哪里做错了,因为我按照了一个 入门教程 和 关于跨包导入的规则。我觉得我的错误可能很小,但我就是找不到,任何帮助都非常感谢。
3 个回答
我在我的setup.py文件里的console_scripts部分写了scriptname.py:main
,其实这里的.py
是多余的。
你需要明确地指定每一个模块。与其每次都在setup.py里添加模块的复杂操作,不如使用来自setuptools
的find_packages
方法。
find_packages
有两个可选参数:
where
,默认值是'.'
,也就是你的当前目录。exclude
,这是一个要排除的内容列表。
我通常在我的代码库里有测试,所以我会使用:
from setuptools import find_packages
packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),
你需要列出所有在 setup
中的包,包括子包:
setup(
name = "mytestmodule",
version = "0.0.1",
description = ("A simple module."),
packages=['mymodule', 'mymodule.subdir'],
)
或者你可以使用 setuptools
的一个神奇功能 find_packages
:
from setuptools import setup, find_packages
setup(
name = "mytestmodule",
version = "0.0.1",
description = ("A simple module."),
packages=find_packages(),
)
这个内容在 这里 提到过:
如果你有子包,它们必须明确列在 packages 中,但 package_dir 中的任何条目会自动扩展到子包。 (换句话说,Distutils 不会扫描你的源代码树,试图找出哪些目录对应于 Python 包,它是通过查找
__init__.py
文件来判断的。)