在Python中处理项目脚本中的路径/可执行文件的最佳实践(例如Django的manage.py或fabric)

Puz*_*d79 13 python fabric

我在一个相当标准化的目录结构中对不同的项目(我是一名科学家)做了很多工作.例如:

project
   /analyses/
   /lib
   /doc
   /results
   /bin
Run Code Online (Sandbox Code Playgroud)

我将所有各种实用程序脚本放在/ bin /中,因为清洁度与敬虔相关.但是,我必须硬编码路径(例如../../x/y/z)然后我必须在./bin/中运行它们或者它们会中断.

我已经使用了Django,它有/manage.py运行各种django-things并自动处理路径.我还使用了fabric来运行各种用户定义的函数.

问题:我该如何做类似的事情?什么是最好的方式?我可以很容易地在/manage.py中写一些内容来将root目录注入sys.path等,但是我希望能够执行"./manage.py foo"运行/bin/foo.py.或者是否可以让Fabric从某个目录中调用可执行文件?

基本上 - 我想要一些简单和低维护的东西.我希望能够将可执行脚本/文件/删除到./bin/中,而不必处理路径问题或导入问题.

做这个的最好方式是什么?

mva*_*een 5

在TLD继续执行

通常,尝试将运行时保持在顶级.这将极大地理顺您的进口.

如果你必须使用相对导入进行大量的导入寻址,那么可能有更好的方法.

修改路径

其他海报都提到了PYTHONPATH.这是在shell中永久执行它的好方法.

如果你不想/不能PYTHONPATH直接操纵项目路径,你可以sys.path用来让自己脱离相对导入的地狱.

运用 sys.path.append

sys.path只是内部列表.您可以附加到其中以添加内容到您的路径中.

说我在/bin这里面的库markdownlib/.您可以附加相对路径sys.path以导入所需内容.

import sys
sys.path.append('../lib')
import markdown


print markdown.markdown("""

Hello world!
------------

""")
Run Code Online (Sandbox Code Playgroud)

明智的话:不要对你的sys.path添加过于疯狂.保持您的架构简单,以避免自己很多混乱.

过于急切的导入有时会导致python模块需要自行导入的情况,此时执行将停止!

使用包和 __init__.py

另一个很棒的技巧是通过添加__init__.py文件来创建python包. __init__.py在目录中的任何其他模块之前加载,因此这是在整个目录中添加导入的好方法.这使它成为添加sys.pathhackery 的理想场所.

您甚至不需要向文件添加任何内容.只需touch __init__.py在控制台上创建一个包就可以了.

有关更具体的示例,请参阅此SO帖子.


Kei*_*ith 4

在当前 shell 中获取(而不是运行)的 shell 脚本中,设置以下环境变量:

PATH=$PATH:$PROJECTDIR/bin
PYTHONPATH=$PROJECTDIR/lib
Run Code Online (Sandbox Code Playgroud)

然后将 Python 模块和包树放入项目的 ./lib 目录中。Python 自动将 PYTHONPATH 环境变量添加到sys.path.

然后,您可以从 shell 运行任何顶级脚本,而无需指定路径,并且会在 lib 目录中查找来自库模块的任何导入。

我推荐非常简单的顶级脚本,例如:

#!/usr/bin/python

import sys
import mytool

mytool.main(sys.argv)
Run Code Online (Sandbox Code Playgroud)

然后您就不必更改它,只需编辑模块代码即可,并且还可以从字节码缓存中受益。