我编写了一个 Python 3 控制台应用程序,它的结构与下面的示例相同。我想知道我应该如何导入模块以实现所需功能部分中指定的行为。
/foo
|-/foo
| |-__init__.py
| |-/bar
| | |-__init__.py
| | |-eggs.py
| |-ham.py
| |-spam.py
|-setup.py
在哪里:
spam
模块有main
功能- 模块导入模块中的
spam
Ham类ham
- 模块导入模块中的
ham
Egg 类eggs
- 两个
__init__.py
文件都是空的 - 导入的基本
setup.py
文件setuptools
所需的功能
我希望能够将控制台应用程序上传到PyPi。然后它可以作为一个包下载
pip
,并在终端中执行。~/>> foo
我还希望能够将它作为 Python 脚本运行。
~/foo>> python3 foo/spam.py
我发现,我认为是一种 hacky 方法来实现这一点。
(hacky)解决方案
为了获得已安装的包和 Python 脚本功能,我添加了一个try: ... except: ...
可行的方法,但它似乎不是正确的方法。
try:
from module import Class # import will work for running as script
except:
# relative import will work for running as a package installed with pip
from .module import Class
如果我只保留相对导入,并尝试将代码作为 Python 脚本运行,我会得到:
Traceback (most recent call last):
File "foo/spam.py", line 6, in <module>
from .ham import Ham
ModuleNotFoundError: No module named '__main__.ham'; '__main__' is not a package
如果我离开常规导入并运行控制台应用程序,则会发生类似情况:
Traceback (most recent call last):
File ".../foo/spam.py", line 6, in <module>
from ham import Ham
ModuleNotFoundError: No module named 'ham'
文件
__init__.py
文件为空
spam.py
"""spam module"""
try:
from ham import Ham
except:
from .ham import Ham
def main():
pass
if __name__ == "__main__:
main()
ham.py
"""ham module"""
try:
from eggs import Egg
except:
from .eggs import Egg
class Ham:
pass
eggs.py
"""eggs module"""
class Egg:
pass
setup.py
from setuptools import setup, find_packages
setup(
name="foo",
version="1.0.0",
author="Pablo",
description="Example",
packages=find_packages(),
entry_points={
"console_scripts": ["foo=foo.spam:main"]
},
)