【问题标题】:adding a subpackage from a different path从不同路径添加子包
【发布时间】:2023-04-03 22:45:01
【问题描述】:

我有一个名为 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。纯蟒蛇。加上一些脚本。

布局是:

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

plugins.py 包含一个插件类。我打算把它放在一个rpm中,然后把它放进去

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

script1 使用这个插件类。但是当我从 git 运行测试它时,如果它没有安装,我希望它也能从 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.extras 使用它,脚本可能找不到 foo 模块。

我对 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 会首先找到本地 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

【问题讨论】:

    标签: python load-path


    【解决方案1】:

    如果我正确理解您的问题,您想使用该模块的开发版本而不是已安装的模块。因此,您可以使用

    1. PYTHONPATH

      来自Module Search Path documentation

      当一个名为 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”附加到它(注意冒号分隔符)。为了使其永久化,请将“PYTHONPATH=value”行添加到文件“/etc/environment”中。

    2. sys.path.insert

      如果您有程序的启动脚本,您可以使用sys.path.insert(0, "somepath") 覆盖模块搜索路径。这类似于您描述的sys.path.append 调用,但将路径插入到列表的开头。

    【讨论】:

    • 这只是问题的一部分。如果你仔细阅读你会发现模块的安装版本和开发版本是不一样的。后一个只是共享顶部包名称(子模块)。
    • @duncan: 为什么“zypp.py”直接安装在/usr/lib64/python2.6/site-packages中?如果您的包包含多个子模块,则不应出现这种情况。布局应该是/usr/lib64/python2.6/site-packages/zypp/X,其中 X 是“init.py”,可能还有其他文件(如插件)。
    • 因为zypp.py有主库类,是swig生成的。而 zypp.plugins 是一个添加了一些实用程序类的模块。一个模块可以同时是一个包吗?
    • @duncan:由于模块是单个文件,因此您不能在其中包含基于文件的子模块(就像它是一个包一样)。此外,您只能覆盖模块搜索路径,但 IMO 无法从目录“A”加载包和从“B”加载子模块。我建议您在开发目录中同时构建 zypp 模块 子模块。由于您有 .so 文件,因此您需要在构建后将它们复制到模块目录。在这种情况下,您必须使用 dev 模块路径覆盖搜索路径,从而有效地使 /usr/lib64/... 路径未被使用。
    猜你喜欢
    • 2020-06-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 2019-01-30
    • 2016-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多