Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何设置多包Python应用程序?_Python - Fatal编程技术网

如何设置多包Python应用程序?

如何设置多包Python应用程序?,python,Python,我的第一个Python应用程序相当小,所有代码都在一个目录中。所有模块只是相互“导入本地_模块”。在主脚本上执行“chmod+x”并运行应用程序很容易 但现在我正在创建一个更大的命令行驱动的应用程序,我希望它能运行数万行代码。所以我想把代码分散在不同的包中。此应用程序仅在工作时在内部运行。目前我们仍在使用Python2.6.6。看起来有两种方法可以组织事情: 我通过让主脚本执行以下操作使应用程序正常工作: import __future__ import absolute_import 然后

我的第一个Python应用程序相当小,所有代码都在一个目录中。所有模块只是相互“导入本地_模块”。在主脚本上执行“chmod+x”并运行应用程序很容易

但现在我正在创建一个更大的命令行驱动的应用程序,我希望它能运行数万行代码。所以我想把代码分散在不同的包中。此应用程序仅在工作时在内部运行。目前我们仍在使用Python2.6.6。看起来有两种方法可以组织事情:

  • 我通过让主脚本执行以下操作使应用程序正常工作:

     import __future__ import absolute_import
    
    然后通过以下方式呼叫:

     python -m main_dir.sub_dir.main_script
    
  • 看起来我还可以更改Python path环境变量,这样我就可以调用main_script.py,或者通过主脚本中的某些内容,例如:

     sys.path.insert(0, os.path.join(THIS_DIR,'..'))
    
  • 我觉得我没有足够的理解来判断什么是设置和使用多包应用程序的最佳方式。我一直在做各种各样的谷歌搜索,找到了很多关于如何运行的参考资料,这些参考资料似乎属于上面列出的两种基本方法。但我还没有找到太多关于设置50000行Python应用程序的信息

    更新:


    凯文,谢谢你的回答。这有助于提高我对Python包的理解,但我仍然有点困惑

    我创建了这个目录结构:
    我的应用程序
    \子包装1
    \子包装2

    在所有三个目录中,我都创建了一个空的uuu init_uuuuu.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))
    
    import sub_package1.sub1
    
    此外,在我的_应用程序中,我在_main_level.py创建了以下内容:

    def double_number(x):
      return 2 *x
    
    最后,在我的_应用程序中,我创建了_main_level_allow.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
    
    和sub11.py:

    import sub1
    
    def subtract1_twice(x):
      return sub1.subtract_1(sub1.subtract_1(x))
    
    现在,当我运行我的_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))
    
    当运行我的_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
    
    [my_app]$python my_main.py
    回溯(最近一次呼叫最后一次):
    文件“/my_main.py”,第8行,在
    导入子_包2.sub2
    文件“/home/hcate/work/temp/my_app/sub_package2/sub2.py”,第2行,在
    从..子包1导入子包1
    ValueError:尝试在顶级包之外进行相对导入
    
    所以我还不知道如何创建一个应用程序,其中一个包中的代码可以使用另一个包中的代码

    我应该做什么不同


    谢谢。

    创建多个包实际上与正确创建单个包没有什么不同

    永远不要混淆“代码所在的目录”和“Python包目录”。也就是说,您应该有一个目录,所有的包和模块都位于其中,比如说它是
    /users/henry/myappcode/
    。在该目录中,可能有一些目录是用于组织代码的Python包;不同之处在于,后一个目录总是出现在导入中(当您使用绝对导入时),而前一个目录永远不会出现。只要这样做,您就不必再去搞
    sys.path

    以下是如何使用正确的路径启动应用程序,以便导入工作正常:

  • 简单的入门版本。您有如下文件:

     my_app_main.py
     my_app/__init__.py
     my_app/module1.py
     my_app/module2.py
     my_app/subpackage/...
     my_app/...
    
    您可以这样运行它,从任何目录,使用绝对或相对路径:

     python /users/henry/myappcode/my_app_main.py
    
    当您使用Python脚本的路径调用Python时,Python会自动将该脚本的位置(而不是当前目录)放在
    sys.path
    上,因此您的所有
    .py
    文件将自动能够
    导入my_app.module
    等等

  • 上面的缺点是它有一个“主脚本”,它与模块不同,并且与代码的其余部分不在同一个包中。您已经知道了
    python-m
    ,因此在本例中使其工作的方法是:

     PYTHONPATH=/users/henry/myappcode python -m my_app.main
    
    假设您创建了
    my_app/main.py
    ,而不是如上所述的
    my_app\u main.py

  • 选择2是丑陋的。使其美观的方法是使Python包可安装(
    setup.py
    )。使用
    entry\u points
    选项,您可以自动创建一个shell脚本,该脚本执行与上述命令相同的操作,但用户只需在安装后键入
    my\u app

    如果您想进行开发,而不必每次都运行
    python setup.py install
    ,而是使用一个方便的命令,那么只需编写指向代码的shell脚本即可

     #!/bin/sh
     PYTHONPATH=/users/henry/myappcode exec python -m my_app.main "$@"
    

  • 在目录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))
    
    import sub_package1.sub1
    
    如果执行“python my_app/my_main.py”,则设置python的路径,以使my_app不是一个包,而是一个包含顶级包的目录。这就是为什么您以后的相对导入会失败,因为
    相对导入超出了顶级包
    :您已将
    子包1
    安排为顶级包

    这里有一条一般规则:决不能在命令行上命名包目录。您可以使用
    -m
    (上面的选项2和3)命名包,也可以调用不在包内的脚本(选项1)


    您的相对导入是正确的,但它失败了,因为Python没有将
    my_app
    视为一个包。确保您遵循选项1(主脚本
    my_app
    )或选项2(主脚本使用
    -m
    启动)。

    Kevin,感谢您的回答。我仍然在为如何设置Python应用程序而挣扎