【问题标题】:Import binary package from different directory从不同目录导入二进制包
【发布时间】:2018-06-22 14:08:47
【问题描述】:

我的目录结构如下:

root
  /src
    file1.py
    file2.py
  /libs
    __init__.py
    package.so

我希望在file1.py 中导入package.so

我尝试了以下导入语句无济于事:

from .libs.package import func
from libs.package import func
from .libs import package
from libs import package

我想避免设置PYTHONPATH / sys.path

有没有简单的方法来做到这一点?我认为这个问题是由于包是一个共享对象而不仅仅是一个 Python 文件 - 我无权访问它的源代码。

谢谢, 亚当

【问题讨论】:

  • 你可以。例如,如果package.sofile1.py 在同一目录中,import package 就可以正常工作。我只是希望将二进制包放在一个单独的目录中。
  • stackoverflow.com/questions/4383571/… 告诉我没有干净的方法可以做到这一点。
  • @AdamMitchell 有什么最新进展吗?
  • A nice approach 到 modify-sys.path 解决方案。

标签: python python-2.7


【解决方案1】:

如果您打算不使用sys.path.append 导入文件,我可以使用file1.py 中的以下sn-p 来做到这一点:

import imp
import os
file = os.sep+os.path.join(*os.path.realpath(__file__).split(os.sep)[:-1]+['..','libs','package.so'])
package = imp.load_source('root.libs.package', file)
print package.a()

打印<root.libs.package.a instance at 0x101845518>。请注意,我的 package.so 文件只是一个 python 文件,它定义了一个虚拟类a,以便我可以测试导入它。根据我的阅读,我相信用imp.load_dynamic 替换imp.load_source 可能是您想要的。

分解:

os.path.realpath(__file__).split(os.sep)[:-1] 以字符串列表的形式为您获取当前运行脚本所在目录的路径。

+['..','libs','package.so'] 将包含父目录 (..)、libs 目录和您的文件名的列表连接到该列表,以便 os.path.join 构建到 package.so 文件的完整路径.

os.path.join(*[that list]) 将列表元素解压缩为os.path.join 的参数,并将字符串与os.sep 连接起来。我还添加了一个前导 os.sep,因为它是一个绝对路径。

imp.load_source 返回从文件路径加载的名称为 root.libs.package 的模块。

This 源代码对于编写此答案很有用,hereimp 模块的文档,您可能会发现它也很有用。

【讨论】:

  • 尽管我很欣赏这个答案,但这种方法破坏了我的问题的重点。也许我应该明确表示我不只是想避免使用sys.path.append,我想要一个干净整洁的单行解决方案。唉,这个好像不存在。
【解决方案2】:

您可以使用 python 文档中描述的相对导入:-here

此外,它仅适用于包下不会要求超出导入的目录。如果是这样,就会出现这个错误:-

valueError: attempted relative import beyond top-level package

您也可以参考这个问题:- value error for relative import

【讨论】:

    【解决方案3】:

    为了从上面的目录导入文件,你应该使用..

    在您的情况下,您需要使用以下行之一进行导入:

    from ..libs.package import func
    from ..libs import package
    
    from root.libs.package import func
    from root.libs import package
    

    请记住,根据 python 文档,最好使用完整路径而不是 ..,因此 from root.libs 是更好的选择。

    关于不能向上遍历:如果你的主脚本是file1.py,你应该从包含root的目录开始,像这样:

    python -m root.src.file1 args

    这样python会将你的根视为一个包。

    最后但同样重要的是:当您使用 Python 2 时,您需要将 __init__.py 放在每个目录中,包括 srcroot

    【讨论】:

    • 您显然没有尝试使用 .so 文件的任何解决方案。
    猜你喜欢
    • 2021-03-09
    • 2018-02-28
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 2017-03-22
    相关资源
    最近更新 更多