我有相当数量的Python脚本,其中包含可由其他Python脚本使用和引用的可重用代码。但是,这些脚本往往分散在不同的目录中,我发现在我的顶级脚本上包含(通常是多个)sys.path.append调用是有点乏味的。我只是想在同一个脚本中提供'import'语句而不需要额外的文件引用。
目前,我有这个:
import sys
sys.path.append('..//shared1//reusable_foo')
import Foo
sys.path.append('..//shared2//reusable_bar')
import Bar
我的偏好如下:
import Foo
import Bar
我的背景主要是在.NET平台上,所以我习惯于使用* .csproj,* .vbproj,* .sln等元文件来管理和包含源文件之外的实际文件路径引用。这允许我只提供'using'指令(相当于Python的导入),而不暴露所有引用,并允许在多个脚本中重用路径引用本身。
Python是否对此有相同的支持,如果没有,有哪些技术和方法?
答案 0 :(得分:4)
简单的答案是将可重用的代码放在site. packages目录中,该目录位于sys.path中。
您还可以通过在路径中的某处添加.pth文件来扩展搜索路径。 有关详细信息,请参阅https://docs.python.org/2/install/#modifying-python-s-search-path
哦,python 2.6 / 3.0增加了对PEP370的支持,Per-user site-packages Directory
答案 1 :(得分:3)
如果您的可重用文件已打包(即它们包含__init__.py
文件),并且该程序包的路径是PYTHONPATH或sys.path的一部分,那么您应该可以只执行
import Foo
This question提供了更多详细信息。
(注意:正如Jim所说,您也可以将可重复使用的代码放入site-packages
目录。)
答案 2 :(得分:1)
您可以将可重复使用的内容放在site-packages
中。这是完全透明的,因为默认情况下它在sys.path
。
您可以将someName.pth
个文件放入site-packages
。这些文件包含您的实际可重用内容所在的目录。这也是完全透明的。并且不涉及在site-packages
中安装更改的额外步骤。
您可以将可重复使用的内容放在PYTHONPATH
上。这有点不太透明,因为你必须确保它的设置。不是火箭科学,而是完全透明。
答案 3 :(得分:1)
在一个项目中,我想确保用户可以在任何地方放置python脚本(基本上可以用作插件)。我的解决方案是将以下内容放在该项目的配置文件中:
[server]
PYPATH_APPEND: /home/jason:/usr/share/some_directory
这样,这会在程序启动时将/ home / jason和/ usr / share / some_directory添加到python路径。
然后,将字符串拆分为冒号并将这些目录添加到sys.path的末尾只是一个简单的问题。您可能需要考虑将一个模块放在site-packages目录中,该目录包含一个函数来读取该配置文件并将这些目录添加到sys.path中(遗憾的是,我目前没有时间编写示例)
正如其他人所提到的,尽可能多地放入网站包并使用.pth文件是个好主意。但是如果你有一个脚本需要导入一些你不想从其他脚本导入的站点包中的东西,这可能是一个好主意。
(也可能有一种方法可以使用.pth文件来完成此操作,但我喜欢能够在放置其余配置信息的同一位置操作python路径)
答案 4 :(得分:1)
最简单的方法是设置(或添加)PYTHONPATH,并将(或符号链接)模块和包放入PYTHONPATH中包含的路径中。
答案 5 :(得分:0)
我的解决方案是打包一个导入模块的实用程序: my_util在网站包中
import my_util
foo = myutil.import_script('..//shared1//reusable_foo')
if foo == None:
sys.exit(1)
def import_script(script_path, log_status = True):
"""
imports a module and returns the handle
"""
lpath = os.path.split(script_path)
if lpath[1] == '':
log('Error in script "%s" in import_script' % (script_path))
return None
#check if path is already in sys.path so we don't repeat
npath = None
if lpath[0] == '':
npath = '.'
else:
if lpath[0] not in sys.path:
npath = lpath[0]
if npath != None:
try:
sys.path.append(npath)
except:
if log_status == True:
log('Error adding path "%s" in import_script' % npath)
return None
try:
mod = __import__(lpath[1])
except:
error_trace,error_reason = FormatExceptionInfo()
if log_status == True:
log('Error importing "%s" module in import_script: %s' % (script_path, error_trace + error_reason))
sys.path.remove(npath)
return None
return mod