我想检测模块是否发生了变化。现在,使用inotify很简单,你只需要知道你想从哪个目录获取通知。

如何在python中检索模块的路径?


当前回答

如果使用pip,则可以调用pip show,但必须使用正在使用的特定python版本调用它。例如,这些都可能给出不同的结果:

$ python -m pip show numpy
$ python2.7 -m pip show numpy
$ python3 -m pip show numpy

Location: /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python

不要简单地运行$ pip show numpy,因为不能保证不同的python版本调用的是同一个pip。

其他回答

如果你想从你的脚本中知道绝对路径,你可以使用path对象:

from pathlib import Path

print(Path().absolute())
print(Path().resolve('.'))
print(Path().cwd())

慢性消耗病()方法

返回一个表示当前目录的新路径对象(由os.getcwd()返回)

解决()方法

使路径为绝对路径,解析任何符号链接。返回一个新的路径对象:

正如其他答案所说,最好的方法是使用__file__(下面再次演示)。然而,有一个重要的警告,即如果你单独运行模块(即作为__main__), __file__是不存在的。

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

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

and

#/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 

希望这能有所帮助。在测试其他解决方案时,这个警告花费了我大量的时间和混乱。

如果你想从包的任何模块中检索包的根路径,下面的工作(在Python 3.6上测试):

from . import __path__ as ROOT_PATH
print(ROOT_PATH)

主__init__.py路径也可以通过使用__file__来引用。

希望这能有所帮助!

当你导入一个模块时,你可以访问大量的信息。检查dir(a_module)。至于路径,有一个dunder: a_module.__path__。也可以只打印模块本身。

>>> import a_module
>>> print(dir(a_module))
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
>>> print(a_module.__path__)
['/.../.../a_module']
>>> print(a_module)
<module 'a_module' from '/.../.../a_module/__init__.py'>

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

查找被调用脚本的路径 查找当前执行脚本的路径 查找被调用脚本的目录

(其中一些问题已经在SO上被问过,但在这里已经被关闭并重新定向。)

使用__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_link指向file_import_testing.py,内容如下:

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提到了使用inspect模块。

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

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

返回绝对路径。查找当前执行脚本的路径:

inspect.getfile(inspect.currentframe())

(感谢@jbochi)

inspect.getabsfile(inspect.currentframe()) 

给出了当前执行脚本的绝对路径(感谢@Sadman_Sakib)。