我遇到了与运行Flask和Celery的应用程序完全相同的问题。我花了太多时间搜索一个简单的答案。唉,没有。
我不喜欢“python -m”语法,因为这对于在运行代码中调用函数并不是非常实用。考虑到我看似小的大脑,我无法处理任何其他答案。
所以......这是一种错误的方式和漫长的道路。他们两人都工作(对我来说),我确信我会从社区中受到抨击。
走错了路
你可以调用模块直接使用imp
包像这样:
import imp
common = imp.load_source('common', os.path.dirname(os.path.abspath('__file__')) + '/common.py')
result = common.stats() #not sure how you call stats, but you hopefully get the idea
我曾经对自己说,引用的快速搜索是一个没有没有,但我找不到他们......对不起。
很长的路要走
这种方法包括临时追加每个模块到您的位置。这对我的Docker部署非常有用,并且很好地工作,无论容器的目录结构如何。步骤如下:
1)您必须从__init__
文件的父目录中导入相关模块。这实际上是__init__
的全部要点 - 允许其包装中的模块可调用。所以,你的情况,cron/__init__
应该包含:
from . import common
它看起来并不像您的目录去任何比这高,但你会做同样的任何其它软件包水平,直至为好。
2)现在您需要将模块的路径附加到PATH变量。你可以看到什么是在那里,现在通过运行:
sys.path
正如预期的那样,你可能不会看到任何模块在那里。这意味着,当你调用common
模块时,Python无法弄清楚你想要什么。为了添加路径,你需要找出目录结构。您将希望使这种动态适用于更改目录。
值得注意的是,每次模块运行时都需要运行。我不知道你的cron
模块是什么,但在我的情况下,它是芹菜。所以,只有当我激发工人和最初的crontabs时才会运行。
这里是我扔一起下锅(我敢肯定有一个更清洁的方式做到这一点):
curr_path = os.getcwd() #current path where cron is running
parrent_path = os.path.abspath(os.path.join(os.getcwd(), '..')) #the parent directory path
parrent_dir = os.path.basename(os.path.abspath(parrent_path)) #the parent directory name
while parrent_dir <> 'project_name': #loop until you get to the top directory - should be the project name
parrent_path = os.path.abspath(os.path.join(par_path, '..'))
parrent_dir = os.path.basename(os.path.abspath(parrent_path))
在你的情况,因为你有两个目录命名,这可能是一个挑战,“应用程序”。您的顶级“应用”是我的'project_name'。下一步,我们假设您已将其更改为“project_name”。
3)现在,你可以追加为每个模块到PATH变量的路径:
sys.path.append(parrent_dir + '/app')
现在,如果你再次运行sys.path
,你应该看到的路径/app
在那里。
总结:确保您所有的__init__
都有导入,确定要导入模块的路径,将路径附加到PATH变量。
我希望有帮助。
此主题可以帮助您吗? https://stackoverflow.com/questions/11536764/how-to-fix-attempted-relative-import-in-non-package-even-with-init-py 它建议运行daemon1.py使用“python - m ...“语法,或者在模块中定义'__package__'。 – Simpom
由于缺乏服务器访问权限,因此无法运行CLI命令,因此无法提供帮助。 – meera