检索python模块路径

我想检测模块是否已经改变。 现在,使用inotify很简单,你只需要知道你想从中获取通知的目录。

如何检索python模块的路径?

 import a_module print a_module.__file__ 

实际上会给你加载的.pyc文件的路径,至少在Mac OS X上。所以我想你可以做

 import os path = os.path.dirname(amodule.__file__) 

你也可以试试

 path = os.path.abspath(amodule.__file__) 

获取目录以查找更改。

python中有inspect模块。

官方文件

检查模块提供了几个有用的功能来帮助获取有关活动对象的信息,如模块,类,方法,函数,回溯,框架对象和代码对象。 例如,它可以帮助您检查类的内容,检索方法的源代码,提取并格式化函数的参数列表,或获取显示详细回溯所需的所有信息。

例:

 >>> import os >>> import inspect >>> inspect.getfile(os) '/usr/lib64/python2.7/os.pyc' >>> inspect.getfile(inspect) '/usr/lib64/python2.7/inspect.pyc' >>> os.path.dirname(inspect.getfile(inspect)) '/usr/lib64/python2.7' 

正如其他答案所说,最好的办法是用__file__ (下面再次演示)。 但是,有一个重要的警告,那就是如果您自己运行模块(即__main__ ), __file__不存在。

例如,假设你有两个文件(这两个文件都在你的PYTHONPATH上):

 #/path1/foo.py import bar print bar.__file__ 

 #/path2/bar.py import os print os.getcwd() print __file__ 

运行foo.py将输出:

 /path1 # "import bar" causes the line "print os.getcwd()" to run /path2/bar.py # then "print __file__" runs /path2/bar.py # then the import statement finishes and "print bar.__file__" runs 

但是如果你尝试自己运行bar.py,你会得到:

 /path2 # "print os.getcwd()" still works fine Traceback (most recent call last): # but __file__ doesn't exist if bar.py is running as main File "/path2/bar.py", line 3, in <module> print __file__ NameError: name '__file__' is not defined 

希望这可以帮助。 这个告诫在测试其他解决方案时花费我很多时间和困惑。

我也会尝试解决这个问题上的一些变化:

  1. 找到被调用脚本的路径
  2. 找到当前正在执行的脚本的路径
  3. 找到被调用的脚本的目录

(其中一些问题已经被提出,但是已经被重复并重定向到这里)。

使用__file__注意事项

对于您导入的模块:

 import something something.__file__ 

将返回模块的绝对路径。 但是,鉴于以下脚本foo.py:

 #foo.py print '__file__', __file__ 

用“python foo.py”调用它将只返回'foo.py'。 如果你添加一个shebang:

 #!/usr/bin/python #foo.py print '__file__', __file__ 

并使用./foo.py调用它,它将返回'./foo.py'。 从不同的目录调用它(例如,把foo.py放到目录栏中),然后调用它

 python bar/foo.py 

或添加一个shebang并直接执行该文件:

 bar/foo.py 

将返回“bar / foo.py”( 相对路径)。

找到目录

现在从那里去获取目录, os.path.dirname(__file__)也可能是棘手的。 至少在我的系统中,如果从文件所在的目录调用它,它会返回一个空字符串。 恩。

 # foo.py import os print '__file__ is:', __file__ print 'os.path.dirname(__file__) is:', os.path.dirname(__file__) 

会输出:

 __file__ is: foo.py os.path.dirname(__file__) is: 

换句话说,它返回一个空的字符串,所以如果你想把它用于当前文件 (而不是导入模块的文件 ),这看起来并不可靠。 为了解决这个问题,你可以把它包装在abspath的调用中:

 # foo.py import os print 'os.path.abspath(__file__) is:', os.path.abspath(__file__) print 'os.path.dirname(os.path.abspath(__file__)) is:', os.path.dirname(os.path.abspath(__file__)) 

其输出如下所示:

 os.path.abspath(__file__) is: /home/user/bar/foo.py os.path.dirname(os.path.abspath(__file__)) is: /home/user/bar 

请注意,abspath()不能解析符号链接。 如果你想这样做,请使用realpath()。 例如,创建指向file_import_testing.py的符号链接file_import_testing_link,其中包含以下内容:

 import os print 'abspath(__file__)',os.path.abspath(__file__) print 'realpath(__file__)',os.path.realpath(__file__) 

执行将打印绝对路径如下所示:

 abspath(__file__) /home/user/file_test_link realpath(__file__) /home/user/file_test.py 

file_import_testing_link – > file_import_testing.py

使用检查

@SummerBreeze提到使用检查模块。

这似乎工作得很好,而且相当简洁,对于导入的模块:

 import os import inspect print 'inspect.getfile(os) is:', inspect.getfile(os) 

乖乖地返回绝对路径。 但是,为了找到当前正在执行的脚本的路径,我没有看到使用它的方法。

这是微不足道的。

每个模块都有一个__file__变量,它显示了你现在所处的相对路径。

因此,获取模块的目录来通知它很简单,如下所示:

 os.path.dirname(__file__) 
 import os path = os.path.abspath(__file__) dir_path = os.path.dirname(path) 

我不明白为什么没有人谈论这个,但对我来说,最简单的解决方案是使用imp.find_module(“modulename”) (文档在这里 ):

 import imp imp.find_module("os") 

它给出了一个元组的第二个路径:

 (<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>, '/usr/lib/python2.7/os.py', ('.py', 'U', 1)) 

这种方法比“检查”方法的优点是不需要导入模块来使其工作,并且可以在输入中使用字符串。 例如,检查另一个脚本中调用的模块时很有用。

编辑

在python3中, importlib模块应该这样做:

doc的importlib.util.find_spec

返回指定模块的规格。

首先,检查sys.modules以查看模块是否已经被导入。 如果是这样,那么sys.modules [name]。 spec返回。 如果碰巧设置为None,则会引发ValueError。 如果模块不在sys.modules中,那么在sys.meta_path中搜索一个合适的规范,赋予给定的“路径”值。 如果没有规范可以找到,没有返回。

如果名称是子模块(包含一个点),则会自动导入父模块。

名称和包的参数与importlib.import_module()相同。 换句话说,相对模块名称(带有前导点)工作。

所以我花了相当多的时间试图用py2exe做到这一点问题是无论是作为一个python脚本或作为一个py2exe可执行文件运行脚本的基本文件夹。 也可以使其工作,无论是从当前文件夹,另一个文件夹或(这是最难的)从系统的路径运行。

最终我使用这种方法,使用sys.frozen作为py2exe中运行的指示器:

 import os,sys if hasattr(sys,'frozen'): # only when running in py2exe this exists base = sys.prefix else: # otherwise this is a regular python script base = os.path.dirname(os.path.realpath(__file__)) 

命令行实用程序

你可以调整它到一个命令行工具,

 python-which <package name> 

在这里输入图像描述


创建/usr/local/bin/python-which

 #!/usr/bin/env python import importlib import os import sys args = sys.argv[1:] if len(args) > 0: module = importlib.import_module(args[0]) print os.path.dirname(module.__file__) 

使其可执行

 sudo chmod +x /usr/local/bin/python-which 
 import module print module.__path__ 

包支持一个更多的特殊属性, __path__ 。 在执行该文件中的代码之前,它被初始化为包含包含__init__.py的目录名称的列表。 这个变量可以修改; 这样做会影响将来对包中包含的模块和子包的搜索。

虽然此功能通常不是必需的,但它可以用来扩展包中的模块组。

资源

如果使用__file__的唯一警告是当前相关目录是空白的(例如,当从脚本所在的同一目录运行脚本时),那么一个简单的解决方案是:

 import os.path mydir = os.path.dirname(__file__) or '.' full = os.path.abspath(mydir) print __file__, mydir, full 

结果是:

 $ python teste.py teste.py . /home/user/work/teste 

诀窍在于or '.'dirname()调用之后。 它将dir设置为. ,表示当前目录 ,是任何路径相关函数的有效目录。

因此,使用abspath()并不是真正需要的。 但是,如果您仍然使用它,则不需要这个技巧: abspath()接受空白路径并将其正确地解释为当前目录。

从python包的模块中,我不得不引用与包相同的目录下的文件。 防爆。

 some_dir/ maincli.py top_package/ __init__.py level_one_a/ __init__.py my_lib_a.py level_two/ __init__.py hello_world.py level_one_b/ __init__.py my_lib_b.py 

所以在上面,我不得不从my_lib_a.py模块中调用maincli.py,知道top_package和maincli.py在同一个目录下。 以下是我如何获得maincli.py的路径:

 import sys import os import imp class ConfigurationException(Exception): pass # inside of my_lib_a.py def get_maincli_path(): maincli_path = os.path.abspath(imp.find_module('maincli')[1]) # top_package = __package__.split('.')[0] # mod = sys.modules.get(top_package) # modfile = mod.__file__ # pkg_in_dir = os.path.dirname(os.path.dirname(os.path.abspath(modfile))) # maincli_path = os.path.join(pkg_in_dir, 'maincli.py') if not os.path.exists(maincli_path): err_msg = 'This script expects that "maincli.py" be installed to the '\ 'same directory: "{0}"'.format(maincli_path) raise ConfigurationException(err_msg) return maincli_path 

根据PlasmaBinturong的发布,我修改了代码。

如果您希望在“程序”中动态执行此操作,请尝试以下代码:
我的意思是,你可能不知道模块的确切名称来“硬编码”它。 它可以从列表中选择,也可以不在当前运行使用__file__。

(我知道,它不会在Python 3中工作)

 global modpath modname = 'os' #This can be any module name on the fly #Create a file called "modname.py" f=open("modname.py","w") f.write("import "+modname+"\n") f.write("modpath = "+modname+"\n") f.close() #Call the file with execfile() execfile('modname.py') print modpath <module 'os' from 'C:\Python27\lib\os.pyc'> 

我试图摆脱“全球”的问题,但发现案件不起作用我认为“execfile()”可以在Python 3中模拟由于这是在一个程序,它可以很容易地被放在一个方法或模块重用。