我仍然试图得到一个python 3的悬念,我遇到了一个问题,我可以将.py文件作为一个脚本运行,或者将其作为一个模块导入,但不是两者都可以。
目录结构
test/
__init__.py
test.py
subwayclock/
__init__.py
subwayclock.py
build/
gen/
__init__.py
gtfs_realtime_pb2.py
nyct_subway_pb2.py
__init__.py
在这种情况下,test.py看起来像这样并且工作(rawFEED()是subwayclock.subwayclock中的一个函数):
from subwayclock.subwayclock import *
print(rawFEED())
但是,我不能直接运行脚本,即
python subwayclock/subwayclock.py
因为它给出以下错误:
Traceback (most recent call last):
File "subwayclock.py", line 32, in <module>
from .build.gen.gtfs_realtime_pb2 import FeedMessage
SystemError: Parent module '' not loaded, cannot perform relative import
但是,如果我在subwayclock / subwayclock.py中将import语句修改为state(即删除了前导'。'):
from subwayclock.subwayclock import FeedMessage
我可以直接通过命令行运行subwayclock.py脚本,完美地调用main函数。
但是,当我运行原始的test.py文件时,import语句不再有效,我收到以下错误:
Traceback (most recent call last):
File "test.py", line 1, in <module>
from subwayclock.subwayclock import *
File "/var/www/test/subwayclock/subwayclock.py", line 32, in <module>
from build.gen.gtfs_realtime_pb2 import FeedMessage
ImportError: No module named 'build'
我可以使此脚本独立运行并可导入吗?
您可以使用-m
开关和完全限定的包路径从包中运行脚本
python -m subwayclock.subwayclock
在这种情况下,您可以使用绝对导入而不是相对导入,但是根据模块之间的依赖关系,它可能会导致一些奇怪的行为,其中对象和类在技术上被定义两次(一次在__main__
脚本中,一次当另一个模块导入你的模块时)
执行此操作的正确方法是使用setup.py
脚本创建适当的python包,并使用console_scripts
入口点功能将函数公开为命令行脚本。
你的项目应该像这样组织。
/subwayclock
/subwayclock
__init__.py
subwayclock.py
...
setup.py
你的setup.py看起来像这样
from setuptools import setup, find_packages
setup(name='subwayclock',
version='0.1',
packages=find_packages(),
zip_safe=False,
entry_points = {
'console_scripts': ['subwayclock_script_name=subwayclock.subwayclock:rawFEED'],
}
)
然后你只需安装包
$ python setup.py install
(你也可以使用develop
模式,所以你仍然可以使用它)
$ python setup.py develop
并且您将能够运行该命令行脚本
$ subwayclock_script_name
我将尝试描述你,它是如何工作的,并且还要提供帮助。
首先,python有许多不同的方法可以导入一些。其中一些是相对进口(from .package import somemodule
)
点表示我们要从当前包中导入somemodule
。这意味着我们应该声明我们的包(当我们导入这个模块时,我们从包中导入它,它有一个名字等)
这个导入几乎用在简单的脚本中,你必须知道这一点。 例:
from app import db
其中app
是一个python模块(app.py
文件),db
是一个变量。如果你想了解更多,read the docs。
我真的不知道如何避免这种情况,但如果我是你,我会这样做:
if __name__ == '__main__':
from mypackage.module import function
else:
from .module import function
你也可以在简单的情况下运行python -m package.module.function
,但它不是一个好主意。
或者您可以将包目录添加到PYTHONPATH
变量中。请参阅good answer几乎相同的问题。