使用__init__.py导入库

时间:2012-11-04 16:00:02

标签: python

当我使用os.chdir()从脚本获取包dir时,为什么我的命名空间导入不起作用?

例如,这是我的包结构来演示问题。

testpk/
testpk/bin
testpk/bin/runit.py
testpk/lib
testpk/lib/libcode.py
testpk/lib/__init__.py

这是我的lib代码,它只是打印已导入的

print "I've been imported"

runit.py的内容

#!/usr/bin/python
import  sys, os

if __name__ == "__main__":
    os.chdir('/home/moorepe/src/testpk')   
    print "working path = " , os.getcwd()
    import lib.libcode 

如果我运行runit,我会收到此错误:

moorepe@halifax$ bin/runit.py 
Traceback (most recent call last):
  File "bin/runit.py", line 6, in <module>
    import lib.libcode 
ImportError: No module named lib.libcode

然而,使用python命令行对其进行测试时,它按预期工作:

    cd testpk
    python -c "import lib.libcode
    I've been imported

这可以从bin目录开始:

cd testpk/bin
python -c "import os; os.chdir('/home/moorepe/src/testpk') ; import lib.libcode"
I've been imported

任何人都可以解释出现了什么问题吗?

因此,除了PYTHONPATH之外,python使用当前dir作为路径。

所以这段代码通过添加sys.path.append(“。”)来工作,因为我强制当前工作的dir作为路径添加。

4 个答案:

答案 0 :(得分:1)

如果您将当前目录的'.'添加到sys.path搜索文件夹列表,那么os.chdir()将生效,import lib.libcode应该开始工作:

档案 runit.py

#!/usr/bin/python
import  sys, os

if __name__ == "__main__":
    sys.path[0:0] = ['.']  # prefix current directory to list
    os.chdir('/home/moorepe/src/testpk')
    print "working path =", os.getcwd()
    import lib.libcode

答案 1 :(得分:1)

这是我发现的另一种解决方案:

import sys
import os.path
sys.path.insert(1, os.path.join(os.path.dirname(os.path.realpath(__file__)), 'lib') )

#from pprint import pprint as pp
#pp(sys.path)
import libcode

这样,您的顶级库名称看起来不像lib,而是libcode

“官方”( Pythonic )方式

如果您正在创建python模块,则可能需要查看official documentation。他们建议使用__init__.py以及与您的模块organizational structure匹配的目录结构(这似乎是“Pythonic”做事的方式)。虽然任何传统的 Ruby-ish Java-ish lib目录结构都可以正常工作,只要您了解模块加载路径并进行适当设置,以便您的模块是装载。

答案 2 :(得分:0)

您应确保testpk / lib /位于PYTHONPATH

sys.path.append('/path/to/testpk/lib/') 

是确保您的包裹在PYTHONPATH

中的一种丑陋方式

执行此操作的“正确方法”是将testpk包及其所有子目录放在Python site-packages目录中。

找出site-packages(应该在PYTHONPATH中)的位置。

GET_PYTHON_LIB_CMD="from distutils.sysconfig import get_python_lib; print (get_python_lib())"
python -c "$GET_PYTHON_LIB_CMD" 

会给你这个位置。

答案 3 :(得分:0)

从给定的脚本中,如果要将库添加到相对于脚本本身的sys.path中,可以添加库计算脚本所在位置的位置,如下所示:

#!/usr/bin/env python
# testpk/bin/runit.py
import os
import sys
_op = os.path
# if file is referred to by symlink, make __file__ point to it's actual location
__file__ = _op.realpath(__file__)
# add __file__'s directory's parent directory to the path
sys.path.append(_op.abspath(_op.join(_op.dirname(__file__), "..")))
import lib

def main():
    pass

if __name__ == "__main__":
    main()

然后你可以从任何地方调用你的可执行文件:

% pwd
/tmp
% ./testpk/bin/runit.py 
I've been imported

由于我在重新分配__file__时考虑通过符号链接运行脚本,我甚至会这样做:

% pwd
/tmp
% ln -s ./testpk/bin/runit.py 
% ./runit.py 
I've been imported