我有一个包cclogger
。该目录有一个__init__.py
文件,其中包含一些用于加载配置的代码。当我尝试使用以下命令在该目录中运行文件api_main.py
时...
python -m cclogger.api_main
我得到以下错误: -
config loaded
Instantiating DB with: cclogger/test123@localhost:x
Instantiated ParseCentral
Register parser called by : CitiIndia
Registered parser for email: CitiAlert.India@citicorp.com
Instantiated SmsParseCentral
Register parser called by : Citi Bank
Registered sms parser for address: lm-citibk
Register parser called by : HDFC Bank
Registered sms parser for address: am-hdfcbk
Traceback (most recent call last):
File "/Users/applegrew/Dropbox/Credit Expense/cclogger/cclogger/api_main.py", line 4, in <module>
from .bottle import run, default_app, debug, get
ValueError: Attempted relative import in non-package
错误上方显示的消息来自__init__.py
导入的同一包中的模块。
api_main.py中的代码是: -
import re
import os
from .bottle import run, default_app, debug, get
from .common_util import date_str_to_datetime, UTCOffset, date_filter
#app = Bottle()
default_app().router.add_filter('date', date_filter)
from . import api, dev
@get('/index')
def index():
return "CCLogger API main live and kicking."
if dev:
debug(True)
run(reloader=True, port=9000)
else:
os.chdir(os.path.dirname(__file__))
application = default_app()
我有python 2.7.1。
我做错了什么?您可以在https://github.com/applegrew/cclogger/tree/master/cclogger
查看完整代码答案 0 :(得分:7)
你不能直接将python模块作为脚本运行(我真的不知道原因)。
编辑:原因在PEP338中解释,这是"-m"
选项的规范。
2.5b1的发布显示出令人惊讶的结果(虽然显而易见) 回顾这个PEP和PEP 328之间的相互作用 - 明确的 相对导入不适用于主模块。这是由于 事实上相对进口依靠
__name__
来确定当前 模块在包层次结构中的位置。在一个主要模块中,__name__
的值始终为__main__
,因此显式相对导入 将永远失败(因为它们只适用于包内的模块)。对于2.5版本,建议始终在任何打算用作主模块的模块中使用绝对导入
要测试你的应用程序,请在函数中封装api_main并创建一个运行主循环的顶级main.py文件:
cclogger / api_main.py:
import re
import os
from .bottle import run, default_app, debug, get
from .common_util import date_str_to_datetime, UTCOffset, date_filter
#app = Bottle()
def main():
default_app().router.add_filter('date', date_filter)
from . import api, dev
@get('/index')
def index():
return "CCLogger API main live and kicking."
if dev:
debug(True)
run(reloader=True, port=9000)
else:
os.chdir(os.path.dirname(__file__))
application = default_app()
/main.py :
from cclogger import api_main
if __name__ == '__main__':
api_main.main()
您可以通过键入python main.py
,python -m main
或python -c "import cclogger.api_main; api_main.main()"
来运行您的应用。
PS:感谢您链接完整的源代码,它总是比问题提供的存根更有帮助。
答案 1 :(得分:0)
自Python 2.6起,使用python -m
执行的模块中的相对导入工作正常。如http://www.python.org/dev/peps/pep-0366中所述,当以这种方式执行时,__package__
属性会自动设置在模块上,以便相对导入起作用。导致失败的部分是重新加载器,显然无法设置__package__
。
编辑:看一下代码,我看到这是一个瓶子API。我没有检查瓶子,但它可能与Flask的重新加载器有同样的问题,它通过信任sys.argv
中的内容来尝试重新启动。问题是处理python -m
的代码(位于runpy
模块中)会修改sys.argv
,删除&#34; -m&#34;并将模块名称翻译成文件名(这非常令人沮丧,但我确信他们有充分的理由)。因此,重新加载器实际执行的内容没有&#34; -m&#34;并且设置__package__
的位永远不会触发,导致不支持相对导入。