从其他目录导入二进制包

时间:2018-06-22 14:08:47

标签: python python-2.7

我具有以下目录结构:

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

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

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

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

我希望避免设置PYTHONPATH / sys.path

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

谢谢, 亚当

3 个答案:

答案 0 :(得分:4)

如果您打算不使用sys.path.append来导入文件,则可以使用file1.py中的以下代码片段来做到这一点:

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文件只是一个定义了伪类a的python文件,因此我可以测试将其导入。根据我的阅读,我相信您可能想要用imp.load_source替换imp.load_dynamic

打破现状:

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模块的文档,您可能也会发现它很有用。

答案 1 :(得分:0)

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

它也仅适用于软件包下的目录,该目录不会要求超出导入范围。如果会发生,那么将发生此错误:-

free

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

答案 2 :(得分:0)

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

根据您的情况,您需要使用以下任一行导入:

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