使用setup.py安装包时的导入错误

37 投票
3 回答
29919 浏览
提问于 2025-04-17 18:50

我在用 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 个回答

0

我在我的setup.py文件里的console_scripts部分写了scriptname.py:main,其实这里的.py是多余的。

6

你需要明确地指定每一个模块。与其每次都在setup.py里添加模块的复杂操作,不如使用来自setuptoolsfind_packages方法。

find_packages有两个可选参数:

  1. where,默认值是'.',也就是你的当前目录。
  2. exclude,这是一个要排除的内容列表。

我通常在我的代码库里有测试,所以我会使用:

from setuptools import find_packages

packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]),
55

你需要列出所有在 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 文件来判断的。)

撰写回答