【问题标题】:Building a python wheel : "no module named ______"构建一个 python 轮子:“没有名为 ______ 的模块”
【发布时间】:2021-03-12 14:48:09
【问题描述】:

我正在尝试在一个复杂的程序上构建一个 python 轮子,但我遇到了导入问题。所以我设法在一个基本的例子上重现了它。该程序在直接调用时运行良好,但在尝试从已安装的轮子中导入时无法运行。

这是我的示例结构:

wheel_test
|-setup.py
|-toto
  |-__init__.py
  |-main.py
  |-tata.py
  |-subfolder
    |-__init__.py
    |-titi.py

ma​​in.py

# coding: utf8
from tata import tata
import subfolder.titi as titi

def test_fct():
  t1 = tata()
  print(f't1 number = {t1.random_number}')
  print(f'Is t1 number even: {titi.is_even(t1.random_number)}')

test_fct()

(这里t1tata类的一个实例,它只是在self.random_number中存储一个随机数,而titi.py文件只包含一个is_even(number)函数,告诉一个数字是否是偶数)

启动时运行良好:

>  python "some_path\wheel_test\toto\main.py"
t1 number = 11
Is t1 number even: False

但是,我想用一个安装文件来做一个轮子: setup.py

# coding: utf8
import os
from setuptools import find_packages, setup

root = os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir))
os.chdir(root)

setup(
  name='toto',
  packages=find_packages(),
  version='0.1',
  description='Wheel test',
  author='Arkeen',
  license='None',
)

(我从[this post] 复制了os.chdir 行)

这将创建一个toto-0.1-py3-none-any.whl 文件。然后我运行$ pip install path_to_newly_created_whell/toto-0.1-py3-none-any.whl,看起来还可以。

但是当我想运行这段代码时:

# coding: utf8
import toto.main as maintoto
maintoto.test_fct()

我收到以下错误:

File "some_path\wheel_test\toto\main.py", line 2, in <module>
  from tata import tata
ModuleNotFoundError: No module named 'tata'

那么为什么会这样呢?为什么这段代码在 python 上运行良好,而不是作为轮子?


编辑:感谢@Countour-Integral 为我指明了正确的方向。不过,我必须深入了解 Python modulespackages、相对和绝对 import 才能完全理解这一点。因此,对于这里有类似问题的任何人,我建议您阅读以下内容:

【问题讨论】:

    标签: python python-import python-module python-packaging python-wheel


    【解决方案1】:

    您得到一个ModuleNotFoundError,因为解释器正在搜索一个名为tata 的全局模块,而不是在当前目录中查找。您也在第一个代码块中重复此行为。

    在下面的 sn-p 中,您将 main.py 运行为 python path/to/main.py

    import subfolder.titi as titi # Does not throw any error
    

    这不会引发任何错误的原因是,您没有main 作为一个包运行,因此当您引用subfolder 时,它会检查您当前的工作目录。

    当您尝试运行setup.py 进行构建时,解释器会将所有内容作为包运行,因此不会查看任何本地目录。您必须像这样更改您的导入

    # notice the .
    from .subfolder import titi 
    from .tata import tata 
    

    你的文件结构看起来像这样

    -> module (directory)
    ---- main.py
    ---- tata.py
    ----> subfolder (directory)
    -------- titi.py
    

    要将其中任何一个作为模块运行,而不是使用python main.py,您必须 cd 1 步后退,进入module 的父目录并使用python -m module main.py并确保您正在使用导入。引用同一目录中的文件。通常这就是python-pip包的开发方式,以便在setup.py过程中更容易。

    【讨论】:

    • 谢谢,我终于明白了:)
    猜你喜欢
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    • 2017-12-30
    • 2021-04-04
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多