我希望检测模块是否发生了变化。现在,使用inotify很简单,你只需要知道想要从中获取通知的目录。
在Python中,如何获取模块的路径?
import a_module
print(a_module.__file__)
实际上会给你加载的 .pyc 文件路径,至少在 Mac OS X 上是这样。所以我猜你可以这样做:
import os
path = os.path.abspath(a_module.__file__)
你也可以尝试:
path = os.path.dirname(a_module.__file__)
获取模块的目录。
__file__
不是一个完整的路径,而是相对路径)。对于我所在的文件,我不得不从同一目录中导入另一个模块并执行如此所示的操作。有没有更方便的方法? - Ben Bryantself.__file__
。 - Dan Passaroos.path.dirname(__file__)
可以正常工作,返回模块所在目录的绝对路径。 - NiccolòAttributeError: 'module' object has no attribute '__file__'
- Dorian Dorepath = module.__path__.__dict__["_path"][0]
,但我不确定它是否具有可移植性或是否会因 Python 版本的不同而产生差异。这个方法对我有效,不像这个答案给出了相同的错误,并且 inspect
的答案会引发一个 TypeError:<module 'module'(namespace)>是一个内置模块
的错误…… - JezorPython自带有一个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'
inspect
获取当前文件的名称;请参考 https://dev59.com/T3VD5IYBdhLWcg3wNY1Z#50905。 - z0rinspect.currentframe()
的信息。 - erikbstackinspect.getfile()
方法无法使用在模块_io
上,但可以用于模块io
。 - smwikipediainspect.getfile
对于内置模块可能会抛出 TypeError
。 - Alex Reinking正如其他答案所说,最好的方法是使用__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
__file__
` 变成 __file__
- fncompNameError
错误?@Paul Du Bois:我尝试过 Python 2.3-3.4 版本,无论是通过 python a.py
、python -ma
还是 ./a.py
运行 Python 文件,__file__
都已定义。 - jfs我还将尝试解决一些与此问题有关的变化:
(这些问题中的一些已经在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 放在目录 bar 中),然后调用以下任一命令:
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)。
inspect.getabsfile(inspect.currentframe())
可以获得当前执行脚本的绝对路径。 - Sadman Sakib我不明白为什么没有人谈论这个,但对我来说最简单的解决方法是使用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))
此方法优于“inspect”方法的原因在于您无需导入模块即可使其工作,并且可以使用输入中的字符串。例如,当检查在另一个脚本中调用的模块时非常有用。importlib.util.find_spec
文档:importlib.util.find_spec
的函数,用来代替旧版的imp.find_module
函数。如果有人需要使用它,可以尝试这个代码片段:importlib.machinery.PathFinder().find_module("os").get_filename()
,它能够找到并返回一个模块的文件名。 - Torxedimp
模块已被废弃,建议使用 importlib
。以及 "AttributeError: module 'importlib' has no attribute 'find_module"。 - Peter Krauss这很简单。
每个模块都有一个__file__
变量,显示它相对于您当前位置的路径。
因此,获取通知其目录的模块非常简单:
os.path.dirname(__file__)
__file__
总是一个绝对路径。 - user3064538import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
__file__
只是dir/test.py,所以在我的Linux python 2.6上无法工作。abspath涉及cwd以完成路径名,这不是期望的结果。但如果您导入一个模块,则m.__file__
会给出期望的结果。 - Ben Bryantimport module
print module.__path__
包支持一个特殊的属性
__path__
。它被初始化为一个列表,其中包含在执行该文件中的代码之前,包含包的__init__.py
的目录的名称。可以修改此变量;这样做会影响将来搜索包中包含的模块和子包。虽然这个特性不经常使用,但它可以用于扩展在一个包中找到的模块集。
如果您想在不加载模块的情况下检索模块路径:
import importlib.util
print(importlib.util.find_spec("requests").origin)
示例输出:
/usr/lib64/python3.9/site-packages/requests/__init__.py
pytest
进行覆盖率测试时,如果在调用pytest之前导入正在测试的模块,则所有导入、类/函数定义等都将被标记为未覆盖,因为它已经被导入了。 - Kashyap您可以将其调整为命令行实用程序,
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
__file__
未设置的情况。 - erikbstackinspect
的解决方案还适用于execfile()
情况下__file__
静默产生错误名称的情况。 - jfsimport pathlib, module; pathlib.Path(module.__file__).resolve().parent
这行代码是跨平台的,作用是导入pathlib和module模块,获取module模块所在文件的绝对路径,并返回其父目录的路径。 - MortenB