从不同路径添加子包

1 投票
1 回答
926 浏览
提问于 2025-04-16 04:48

我有一个叫做zypp的Python包。这个包是通过swig生成的,rpm包(叫做python-zypp)把它放在:

rpm -ql python-zypp
/usr/lib64/python2.6/site-packages/_zypp.so
/usr/lib64/python2.6/site-packages/zypp.py

现在,我有一个不同的项目,提供了一些额外的API。这些都是纯Python的,还有一些脚本。

它的结构是:

bin/script1
python
python/zypp
python/zypp/plugins.py
python/zypp/__init__.py

plugins.py里面有一个Plugin类。我打算把这个放进一个rpm包里,然后放到

/usr/lib64/python2.6/site-packages/zypp/plugins.py

script1使用这个Plugin类。但是在我从git测试运行的时候,我希望它能在没有安装的情况下也能找到这个模块。所以它有类似这样的代码:

sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../python'))
from zypp.plugins import Plugin

不过,似乎如果python-zypp安装在/usr/lib64/python2.6/site-packages/zypp.py这个位置,script1就找不到plugins这个子模块了。如果我卸载python-zypp,它就能找到。

所以我的问题是,是否可以通过添加子模块来扩展一个模块,而这些子模块位于不同的加载路径?或者它们总是会冲突?

打个比方,我有一个模块foo。我在一个不同的加载路径下提供foo.extras(这个可能确实会用到foo)。如果系统加载路径中先找到了foo,脚本就找不到foo.extras。如果我只使用自定义加载路径,脚本可能找不到foo模块,因为foo.extras使用了它。

我对ruby更有经验,但在ruby中我可以安装:

/usr/lib64/ruby/gems/1.8/gems/foo-1.0/lib/foo/*

然后我可以在我的脚本中:

bin/script
lib/foo/extras/*

我可以在脚本中这样做:

$: << File.join(File.dirname(__FILE__), "../lib"

然后我的脚本可以

require foo
require foo/extras

无论foo/extras是安装在系统上还是在自定义加载路径中,它们都不会冲突。

相反,我发现使用PYTHONPATH时,local zypp.plugins会优先被找到。但这样一来,安装的zypp模块就找不到了:

import zypp # works, but seems to import the local one
from zypp.plugins import Plugin # works, PYTHONPATH finds it first

repoinfo = zypp.RepoInfo() # does not work

1 个回答

2

如果我理解你的问题没错的话,你是想用这个模块的开发版本,而不是已经安装的版本。你可以这样做:

  1. PYTHONPATH

    根据模块搜索路径的说明

    当导入一个叫做spam的模块时,解释器会先在当前目录中寻找一个叫spam.py的文件,然后再去环境变量PYTHONPATH指定的目录列表中查找。这和shell中的PATH变量的格式是一样的,都是一个目录名称的列表。如果PYTHONPATH没有设置,或者在这些地方找不到文件,搜索会继续在一个默认的安装路径中进行;在Unix系统上,这个默认路径通常是.:/usr/local/lib/python。

    所以,如果模块目录的GIT树在"/home/username/some/path",你就需要把PYTHONPATH改成"/home/username/some/path"。或者如果PYTHONPATH变量已经在使用中,你可以在后面加上":/home/username/some/path"(注意用冒号分隔)。为了让这个设置永久生效,可以在"/etc/environment"文件中添加一行"PYTHONPATH=value"。

  2. sys.path.insert

    如果你有一个程序的启动脚本,你可以用sys.path.insert(0, "somepath")来覆盖模块的搜索路径。这和你提到的sys.path.append类似,但它是把路径插入到列表的最前面。

撰写回答