2011-04-19 49 views
4

所以Python路径的行为是不同的PERL5LIB这使得它有点难以库划分为不同的回购协议。 让我描述它是如何工作的PERL:行为PYTHONPATH的VS PERL5LIB

如果目录结构如下:

项目/ lib目录/酒吧/ foo.pm
的common/lib /酒吧/ baz.pm

现在PERL5LIB被设置为 '项目/ lib目录下:common/lib目录' 在我的perl脚本

我可以这样做:

use bar::foo; # this comes from project/lib/bar/foo.pm 
use bar::baz; # this comes from common/lib/bar/baz.pm 

在Python虽然具有相同的目录结构(与.py文件代替),并添加相同的迪尔斯到PYTHONPATH(当然在项目/ lib目录/酒吧和common/lib目录/条迪尔斯添加虚__init__.py):

import bar.foo # this successfully imports from project/lib/bar/foo.py 
import bar.baz # this fails! 

Python有没有办法解决这个问题,因为这会使分区代码变成一场噩梦。

编辑:更清晰一点,其中__init__.py文件。

+1

延伸阅读:http://stackoverflow.com/questions/3346482/pythonpath-hell-with-overlapping-package-structures – jathanism 2011-04-20 00:04:44

+0

“这失败了!”这是什么意思?你会得到什么错误? – 2011-04-20 01:34:06

+0

参见PEP 382:http://www.python.org/dev/peps/pep-0382/(这是正在审议的一项可能增加的Python 3.3) – ncoghlan 2011-04-20 03:11:17

回答

3

你的第一个问题是,你试图迫使一个Perl范式成Python。你的第二个问题是你似乎不了解Python命名空间系统是如何工作的。您不能将相同的包两次导入到全局名称空间中。它只是不能这样工作。

的Python将使用它找到的第一个匹配。因为它,当你从第一位置导入bar.foo是查找包bar,它甚至没有尝试后者,当您尝试导入bar.baz驻留在后者的位置。

当你导入它被添加到全局命名空间,并且还跟踪在sys.modules字典的模块。用新鲜的Python解释器开始,如果导入sys你看到它是在全局命名空间:

>>> import sys 
>>> globals().keys() 
['__builtins__', '__name__', 'sys', '__doc__', '__package__'] 

如果通过按键得到它,你得到的模块对象:

>>> globals()['sys'] 
<module 'sys' (built-in)> 

现在,如果您导入foo你看到它在全局命名空间太也结束了:

>>> import foo 
>>> globals().keys() 
['__builtins__', '__package__', 'sys', '__name__', 'foo', '__doc__'] 

而且也sys.modules

>>> sys.modules['foo'] 
<module 'foo' from 'foo.pyc'> 
>>> globals()['foo'] 
<module 'foo' from 'foo.pyc'> 

即使你从全局命名空间中删除foo,它仍然驻留在sys.modules

>>> del foo 
>>> 'foo' in globals() 
False 
>>> 'foo' in sys.modules 
True 

这是为什么?将sys.modules想象为已导入模块的注册表。这是作为优化完成的,所以如果您导入同一个包的多个部分,那么已经加载的部分不会继续重新加载。真正“卸载”模块的唯一方法是从sys.modules和全局名称空间中删除它。

我希望通过说明这一点,你也看到,每个包或模块对象只能在任何给定程序的命名空间驻留一次。这就是为什么你想要做的是失败。蟒蛇已经成功地引进bar的第一次,所以它不会尝试重新导入第二次。

如果你真的想用同样的包名两种截然不同的路径驻留在文件系统中不同的位置,你应该研究Python的namespace packages。这将允许您将软件包安装在将自己绑定到其他软件包的名称空间的备用位置。

参见:

+0

+1:很不错的解释。代码片段确实也有帮助。谢谢! – 2011-04-20 01:02:52

+0

虽然与使用Python的鸡蛋中的一个可以具有不同的目录具有相同名称被用作模块分母。 (用Perl共享这些可能是艰难的,但也许增加了对每个蟒蛇蛋结构PERL5LIB的条目) – jsbueno 2011-04-20 03:58:53

+0

谢谢你的提示! – viral 2011-04-20 22:25:34