Python ImportError(很可能是由于循环导入)用于 pip 安装而非本地 setup.py

Python ImportError (most likely due to a circular import) for pip install but not local setup.py

我有一个简单的 Python 包,用于绘制名为 pliffy 的科学数据。代码托管在 this repo. I have published it on PyPi here 中的 Github。

我收到一位试图使用该软件包的同事发来的 Github issue。基本上,执行 pip install pliffy 会安装包,但是当您启动 Python 解释器并尝试导入包时,您会收到以下错误消息:

ImportError: cannot import name 'figure' from partially initialized module 'pliffy' (most likely due to a circular import) ([...]/testing/pliffy/venv/lib/python3.8/site-packages/pliffy/__init__.py)

在创建一个新的 Python 环境并 pip 安装我的包后,我已经能够在我自己的机器上重现这个问题(是的,我现在知道在你推送它们之后测试你自己的包的重要性到 Pypi;不会再犯这个错误了!)

但是,如果我执行以下操作——克隆和本地安装——我不会收到错误消息:

git clone https://github.com/MartinHeroux/pliffy.git
cd pliffy/
python3 -m venv venv
source venv/bin/activate
python setup.py build
python setup.py install
python
>>> import pliffy
>>> pliffy.demo.demo()

我 运行 在使用我自己的 classes/objects 类型提示时遇到循环导入问题,但我认为我已经解决了所有问题,因为我能够在本地安装和使用我的包。

我确实尝试将 plot.py 模块中的导入语句更改为仅导入 pliffy 而不是 from pliffy import estimate, figure, parse,但这并没有解决问题。而且因为问题似乎只在我创建 Python 轮并将其推送到 PyPi 之后出现,所以我必须碰撞并推送一个版本才能弄清楚它不起作用(即它在我安装本地打包)。

如果它有用,下面是我如何创建我的轮子并将我的包推送到 PyPi:

pip install twine
python setup.py sdist bdist_wheel
twine upload --repository-url https://test.pypi.org/legacy/ dist/* # as a test 
twine upload dist/*

非常感谢任何对此问题的帮助。


更新:附加信息

亲爱的贾斯汀,感谢您花时间阅读我的问题并询问更多信息。

为了回答你的问题,我创建了一个本地环境,在本地安装了我的包(即 pliffy),并在包中启动了一个 Python 解释器 not文件夹。我在尝试导入我的包时收到一条错误消息,但这次出现了不同的错误:

>>> import pliffy
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<frozen zipimport>", line 259, in load_module
  File "/home/martin/Desktop/venv/lib/python3.8/site-packages/pliffy-0.1.2-py3.8.egg/pliffy/__init__.py", line 4, in <module>
ImportError: cannot import name 'figure' from 'pliffy' (/home/martin/Desktop/venv/lib/python3.8/site-packages/pliffy-0.1.2-py3.8.egg/pliffy/__init__.py)

这告诉我之前我没有收到错误,因为我在包目录中时启动了 Python 解释器。为什么我在启动包文件夹中的 Python 解释器 not 时出现错误(并且是另一个错误)我不清楚。

Dustin,你还问了导入结构。我不太确定有多少(小)信息,但我决定提供所有信息:

pliffy
├── __init__.py             
├── demo.py
├── estimate.py
├── parser.py
├── plot.py
├── utils.py
└── figure
    ├── diff_axis.py
    ├── figure_ab.py
    ├── figure_diff.py
    ├── figure.py
    └── __init__.py

init.py [API 只需要底部的两个导入,但需要其他导入才能让我的测试套件工作(这可能不需要,但是当我编写代码时,我无法测试这些其他模块,除非我在这里包括了明确的进口)。]

from . import estimate
from . import plot
from . import utils
from . import figure
from . import parser
from . import demo
from pliffy.plot import plot_abd
from pliffy.utils import PliffyInfoABD, ABD

demo.py

from pliffy.utils import PliffyInfoABD, ABD
from pliffy.plot import plot_abd

estimate.py

from pliffy.utils import ABD

parser.py

from pliffy import estimate
from pliffy import utils

plot.py

import pliffy

utils.py

from pliffy import estimate

图/init.py

from .figure import Figure
from .figure_ab import FigureAB
from .figure_diff import FigureDiff
from .diff_axis import DiffAxCreator

figure/diff_axis.py

from pliffy import utils, parser

figure/figure.py

from pliffy.parser import Xticks, Raw, Mean, CI, Paired

figure/figure_ab.py

from pliffy.figure import Figure
from pliffy import parser

figure/figure_diff.py

from pliffy.figure import Figure
from pliffy import parser

如果需要更多信息,请告诉我。

我查看了您发布的 wheel,确实它不包含您的 figure 子包。

为了了解原因,让我们检查一下您的 setup.py

您将您的包声明为 packages=["pliffy"] 但您没有声明 pliffy.figure 子包。正因为如此,轮子包装商才没有拿走。

更好的标准方法是使用 setuptools find_packages() 功能来为您发现包。

packages=find_packages()