构建一个巨蟒轮:&没有名为_的模块

问题描述

我正在尝试在一个复杂的程序上构建一个Python轮子,但我在导入方面遇到了问题。所以我设法在一个基本的例子中再现了这一点。该程序在直接调用时运行正常,但在尝试从已安装的轮子导入时不运行。

以下是我的示例结构:

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

main.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_pathwheel_test	otomain.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_pathwheel_test	otomain.py", line 2, in <module>
  from tata import tata
ModuleNotFoundError: No module named 'tata'

那么为什么会出现这样的结果呢?为什么这段代码可以很好地与Python一起运行,但不能像轮子一样运行?


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

  • Python Modules and Packages – An Introduction
  • Absolute vs Relative Imports in Python

解决方案

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

在以下代码片断中,您以python path/to/main.py

身份运行main.py
import subfolder.titi as titi # Does not throw any error

这不会引发任何错误的原因是,您没有作为程序包运行,因此当您引用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,您必须后退1步,进入module的父目录,然后使用python -m module main.py、,并确保将Imports与一起使用。若要引用同一目录中的文件,请执行以下操作。为了在setup.py过程中更轻松,通常就是这样开发python-pip包的。

相关文章