我正在制作一个简单的python应用程序。我不知道我做的是否正确,所以请在评论中纠正我,或者如果你对此有答案
错误:
ImportError: No module named 'taskhandler'
以及:
^{pr2}$文件结构:
.
├── 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
'任务模式/皮多.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 = 'abhishtagatya@yahoo.com',
packages = ['task_mod'],
scripts = ['task_mod/pydo'],
python_requires = '>=3',
include_package_data = True,
zip_safe = False
)
我如何解决这个问题?在
注意:如果我运行python3 task_mod/pydo.py
它可以正常工作!但是当我试着测试它的时候,它给出了两个重要因素。在
首先,请注意,您在}。因为您没有在库中提供
setup.py
中提供了一个名为task_mod
的包。这意味着,你应该只import task_mod
或import task_mod.blah
,永远不要{blah
。把进口改成绝对进口。在第二,如果您仍然需要相对导入(这是使用单个库的常见做法-那么维护代码更容易),您应该相对导入:
from .styles import termcolor
(注意点)。在第三,相对导入只影响模块和包,而不是直接执行的脚本(因为},它会改变一切)。对于脚本,您有两个选择来正确执行:
pydo.py
是包__main__
,而不是{选择A(so-so):总是在皮多.py;还有
from task_mod.styles import termcolor
,等等)。在选择B(最佳实践):不要将任何脚本导出为库的一部分(仅用于构建/测试/CI/CD)。相反,导出控制台脚本的入口点(google:setuptools入口点)。在
setup( .... entry_points={ 'console_scripts': [ 'pydo = task_mod.pydo:main', ], }, )
当然,在该模块中定义
main()
函数。在shebang(
#!...python3
)在这里完全不相关。在升级版:
如果您在进口方面遇到问题,请记住:
您应该以某种方式使您的包位于PYTHONPATH env var(或
sys.path
内部变量)上。当您执行import things
时,这正是Python查找内容的地方。在您可以在任何导入之前
print(sys.path)
来了解为什么会这样-第一个元素将是脚本的dir,它将在task_mod/pydo.py
&;setup.py
调用之间变化。在在主项目目录(
python3 setup.py
)中运行脚本时,sys.path
以项目的目录开始。task_mod
在那里,你可以导入它。另外,当您执行pip install -e .
之类的操作时,这些包也将被“安装”到Python/virtualenv库列表中,但方式不同。在但是,当您运行
python3 task_mod/pydo.py
时,您当前的dir是.../task_mod/
。在那里,您找不到task_mod
包(因为它是上面一级的)。在相反,当您运行
python3 setup.py
时,您当前的dir是项目的dir,您不能像最初那样直接导入styles
&;taskhandler
(不加前缀task_mod.
)。在这正是为什么您不应该依赖
sys.path
,也不应该直接使用脚本,并假定它的位置。因为它是变化的。在您可以尝试运行
PYTHONPATH=. python3 task_mod/pydo.py
,使其与forsetup.py
相同(或者PYTHONPATH=./task_mod/ python3 setup.py
使其与fortask_mod/pydo.py
相同)。但这是一个肮脏的黑客让它工作。相反,您应该根据Python的约定正确地布局库。在必须指定中使用的所有模块设置.py,而不仅仅是顶层文件夹。所以在你的设置.py文件,将
packages = ['task_mod'],
替换为packages = ['task_mod', 'task_mod.styles', 'task_mod.taskhandler'],
。在或者,在不更改}导入。然后可以使用
setup.py
的情况下,可以使用import task_mod.styles
或{styles.termcolor
等样式的文件。在或者,您可以使用setuptool的黑魔法函数
find_packages
,如下所示:packages = find_packages(),
Related SO post
相关问题 更多 >
编程相关推荐