我的第一个Python应用程序相当小,所有的代码都在一个目录中。所有模块都只是相互“导入local_module”。在主脚本上执行"chmod +x“并运行应用程序很容易。
但是现在我正在创建一个更大的命令行驱动的应用程序,我希望它会运行到数万行代码中。所以我想把代码分散到不同的包中。此应用程序仅在工作时在内部运行。目前我们仍然在使用Python2.6.6。看起来有几种方法可以构造事物:
我觉得我没有足够的理解来判断什么是建立和使用多包应用程序的最佳方式。我一直在做各种各样的Google搜索,并找到了很多关于如何运行的参考资料,这似乎属于上面列出的两种基本方法。但是,我还没有找到建立一个50,000行Python应用程序的方法。
更新:
凯文谢谢你的回答。它帮助我提高了对Python包的理解,但我仍然有些困惑。
我创建了这个目录结构:
my\_app \ sub\_package1 \ sub\_package2 在这三个目录中,我创建了一个空的__init__.py文件。
在my_app目录中,我用以下内容创建了my_main.py:
import sys
import sub_package1.sub1
import sub_package1.sub11
import at_main_level
import at_main_level_also
def _my_print (someString):
sys.stdout.write("{0}\n".format(someString))
if __name__ == '__main__':
_my_print ("Learning about Python packages and applications.")
x = 3
doubleX = at_main_level.double_number(x)
_my_print ("Double of {0} is {1}".format(x, doubleX))
doubleDoubleX = at_main_level_also.double_double_number(x)
_my_print ("Double Double of {0} is {1}".format(x, doubleDoubleX))
xMinus1 = sub_package1.sub1.subtract_1(x)
_my_print ("{0}-1 is {1}".format(x, xMinus1))
xMinus1Twice = sub_package1.sub11.subtract1_twice(x)
_my_print ("{0}-2 is {1}".format(x, xMinus1Twice))同样在my_app中,我用以下方法创建了at_main_level.py:
def double_number(x):
return 2 *x最后,在my_app中我创建了at_main_level_also.py:
import at_main_level
def double_double_number(x):
return at_main_level.double_number(at_main_level.double_number(x))然后在sub_package1中创建了sub1.py:
def subtract_1 (x):
return x - 1和11分之1:
import sub1
def subtract1_twice(x):
return sub1.subtract_1(sub1.subtract_1(x))现在,当我运行my_main.py时,我得到了对我来说有意义的结果:
Learning about Python packages and applications.
Double of 3 is 6
Double Double of 3 is 12
3-1 is 2
3-2 is 1所以我可以写代码:
1)其中一个模块在顶层使用另一个模块中的代码。
2)上层的模块可以在子包中使用代码,子包中的代码可以调用子包中另一个模块中定义的函数。
但是当我在sub_package2中创建sub2.py时:
from ..sub_package1 import sub1
def subtract_2 (x):
return sub1(sub1(x))添加到my_main.py中
import sub_package2.sub2 在我的主要职能结束时:
xMinus2 = sub_package2.sub2.subtract_2(x)
_my_print ("{0}-1 is {1}".format(x, xMinus2))在运行my_main时,我得到以下信息:
[my_app]$ python my_main.py
Traceback (most recent call last):
File "./my_main.py", line 8, in <module>
import sub_package2.sub2
File "/home/hcate/work/temp/my_app/sub_package2/sub2.py", line 2, in <module>
from ..sub_package1 import sub1
ValueError: Attempted relative import beyond toplevel package因此,我还不明白如何创建一个应用程序,其中一个包中的代码可以在另一个包中使用代码。
我该怎么做?
谢谢。
发布于 2016-03-15 20:58:44
创建多个包实际上与正确创建单个包并无区别。
不要混淆“您的代码所在的目录”和“是Python包的目录”。也就是说,您应该有一个目录,所有的包和模块都在其中运行--假设它是/users/henry/myappcode/。在该目录中,可能有一些目录是用来组织代码的Python包;不同的是,后面的目录总是出现在导入中(当您使用绝对导入时),而前者永远不会出现。只要您这样做,也不需要与sys.path混为一谈。
下面是如何使用正确的路径启动应用程序,以便导入能够正常工作:
sys.path上,因此您的所有.py文件都将自动能够import my_app.module等等。python -m,因此在本例中使其工作的方法是:
PYTHONPATH=/users/henry/myappcode python -m my_app.main
假设您创建的是my_app/main.py而不是上面的my_app_main.py。setup.py)。使用entry_points选项,您可以自动创建一个shell脚本,它与上面的命令相当,但是用户只需要在安装后输入my_app。
如果您想要进行开发,而不必每次运行python setup.py install,但有一个方便的命令,那么只需编写您自己的shell脚本就可以指向您的代码。
#/bin/sh PYTHONPATH=/users/henry/myappcode exec python -m my_app.main "$@“在my_app目录中,我用以下内容创建了my_main.py: 导入sub_package1.sub1
如果您执行'python _app/my_main.py‘,那么Python的路径将被设置为my_app不是一个包,它是一个包含顶级包的目录。这就是为什么以后的相对导入在relative import beyond toplevel package中失败的原因:您已经将sub_package1安排为一个toplevel包。
这里有一条一般规则:您决不能在命令行中命名包目录。您可以用-m命名一个包(上面的选项2和3),也可以调用一个不在包内的脚本(选项1)。
您的相对导入是正确的,但是它失败了,因为Python没有将my_app视为一个包。确保您遵循的是选项1(主脚本而不是 or my_app)或选项2 (main与-m一起启动)。
https://stackoverflow.com/questions/36011221
复制相似问题