我正在制作一个简单的python应用程序。我不知道我是否做对了,所以请在评论中纠正我,或者您是否对此有答案
错误:
ImportError: No module named 'taskhandler'
和:
ImportError: No module named 'styles' while doing `python3 setup.py test
文件结构:
.
├── MANIFEST.in
├── pydotask.egg-info
│ ├── dependency_links.txt
│ ├── not-zip-safe
│ ├── PKG-INFO
│ ├── SOURCES.txt
│ └── top_level.txt
├── README.md
├── setup.py
├── task_mod
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── pydo.cpython-35.pyc
│ │ └── taskhandler.cpython-35.pyc
│ ├── pydo.py
│ ├── styles
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-35.pyc
│ │ │ ├── termcolor.cpython-35.pyc
│ │ │ └── text_style.cpython-35.pyc
│ │ ├── termcolor.py
│ │ └── text_style.py
│ ├── taskhandler.py
│ └── tasks.csv
└── update.txt
5 directories, 22 files
'task_mod / pydo.py':
#!/usr/bin/env python3
''' To Do App in Python '''
import sys, os
import taskhandler as task
from styles import text_style as text
from styles import termcolor
task_mod/taskhandler.py
:#!/usr/bin/env python3
import sys, os
import csv
from styles import termcolor
from styles import text_style as text
setup.py
from setuptools import setup
def readme():
with open('README.md') as readme:
return readme.read()
setup(
name = 'pydotask',
version = '0.2',
description = 'PyDo is a CLI Application to keep you on track with your tasks and projects',
long_description = readme(),
classifiers = [
'Development Status :: 3 - Alpha',
'Programming Language :: Python :: 3.5',
'Topic :: Office/Business :: Scheduling'
],
keywords = 'utilities office schedule task reminder',
url = '',
author = 'Abhishta Gatya',
author_email = '[email protected]',
packages = ['task_mod'],
scripts = ['task_mod/pydo'],
python_requires = '>=3',
include_package_data = True,
zip_safe = False
)
我如何解决这个问题?
注意:如果我运行
python3 task_mod/pydo.py
,它将正常工作!但是,当我尝试对其进行测试时,它会给出2 ImportErrors。 最佳答案
首先,请注意,您在task_mod
中提供了一个名为setup.py
的程序包。这意味着,您只能使用import task_mod
或import task_mod.blah
,而不能使用import blah
。因为您没有在库中提供blah
。尝试将进口更改为绝对进口。
其次,如果您仍然想要相对导入(这是使用单个库的常见做法-这样便更易于维护代码),则应相对导入:from .styles import termcolor
(注意点)。
第三,相对导入仅影响模块和软件包,而不影响您直接执行的脚本(因为pydo.py
是软件包__main__
,而不是task_mod.pydo
,并且它会更改所有内容)。对于脚本,有两种选择可以正确执行此操作:
选择A(一般):始终导入绝对的软件包/模块名称(在pydo.py中输入import task_mod.taskhandler as tashhandler
;还输入from task_mod.styles import termcolor
等)。
选项B(最佳实践):切勿将任何脚本导出为库的一部分(仅用于构建/测试/ CI / CD)。相反,请导出控制台脚本的入口点(google:setuptools入口点)。setup( .... entry_points={ 'console_scripts': [ 'pydo = task_mod.pydo:main', ], },)
并且,当然,在该模块中定义main()
函数。
shebang(#!...python3
)在这里完全无关。
UPD:
如果您在导入时遇到问题,请记住以下几点:
您应该使软件包以一种或另一种方式放在PYTHONPATH env var(或sys.path
内部变量)上。当您执行import things
时,这正是Python查找内容的地方。
您可以在任何导入之前先print(sys.path)
看看为什么会发生这种情况-第一个元素将是脚本的目录,并且在task_mod/pydo.py
和setup.py
调用之间会有所不同。
在主项目目录(python3 setup.py
)中运行脚本时,sys.path
以项目的目录开头。 task_mod
在那里,您可以导入它。同样,当您执行类似pip install -e .
的操作时,这些软件包也将以其他方式“安装”到Python / virtualenv库列表中。
但是,当您运行python3 task_mod/pydo.py
时,当前目录为.../task_mod/
。在这里,您找不到task_mod
软件包(因为它是上一层)。
相反,当您运行python3 setup.py
时,当前目录是项目的目录,并且您不能像最初那样直接导入styles
和taskhandler
(不带task_mod.
前缀)。
这就是为什么您永远不要依赖sys.path
,绝对不要直接使用脚本并假定其位置的原因。因为它变化。
您可以尝试运行PYTHONPATH=. python3 task_mod/pydo.py
以使其与setup.py
相同(或PYTHONPATH=./task_mod/ python3 setup.py
使其与task_mod/pydo.py
相同)。但这是使它工作的肮脏技巧。相反,您应该根据Python的约定正确地布局库。
关于python - 在执行python setup.py测试时ImportError,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46504262/