How to retrieve a module's path?
我要检测模块是否已更改。现在,使用inotify很简单,只需知道要从中获取通知的目录即可。
如何在Python中检索模块的路径?
1 2 | import a_module print(a_module.__file__) |
将实际为您提供加载的.pyc文件的路径,至少在Mac OS X上是如此。因此,我想您可以这样做:
1 2 | import os path = os.path.dirname(a_module.__file__) |
您也可以尝试:
1 | path = os.path.abspath(a_module.__file__) |
获取模块的目录。
python中有
The inspect module provides several useful functions to help get
information about live objects such as modules, classes, methods,
functions, tracebacks, frame objects, and code objects. For example,
it can help you examine the contents of a class, retrieve the source
code of a method, extract and format the argument list for a function,
or get all the information you need to display a detailed traceback.
例子:
1 2 3 4 5 6 7 8 | >>> 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' |
正如其他答案所说,最好的方法是使用
例如,假设您有两个文件(都在您的pythonpath上):
1 2 3 | #/path1/foo.py import bar print(bar.__file__) |
和
1 2 3 4 | #/path2/bar.py import os print(os.getcwd()) print(__file__) |
运行foo.py将提供以下输出:
1 2 3 | /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,您将获得:
1 2 3 4 5 | /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 | import something something.__file__ |
将返回模块的绝对路径。但是,考虑到下面的脚本foo.py:
1 2 | #foo.py print '__file__', __file__ |
用"python foo.py"调用它只返回"foo.py"。如果添加shebang:
1 2 3 | #!/usr/bin/python #foo.py print '__file__', __file__ |
并使用./foo.py调用它,它将返回"./foo.py"。从另一个目录调用它(例如将foo.py放在目录栏中),然后调用
1 | python bar/foo.py |
或者添加shebang并直接执行文件:
1 | bar/foo.py |
将返回"bar/foo.py"(相对路径)。
正在查找目录现在从那里获取目录,
1 2 3 4 | # foo.py import os print '__file__ is:', __file__ print 'os.path.dirname(__file__) is:', os.path.dirname(__file__) |
意志产出:
1 2 | __file__ is: foo.py os.path.dirname(__file__) is: |
换句话说,它返回一个空字符串,因此,如果您想将其用于当前文件(而不是导入模块的文件),那么这似乎不可靠。要解决此问题,您可以将其包装在对abspath的调用中:
1 2 3 4 | # 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__)) |
输出如下:
1 2 | os.path.abspath(__file__) is: /home/user/bar/foo.py os.path.dirname(os.path.abspath(__file__)) is: /home/user/bar |
请注意,abspath()不解析符号链接。如果要执行此操作,请改用realpath()。例如,制作一个symlink文件"导入测试"链接指向文件"导入测试"py,内容如下:
1 2 3 | import os print 'abspath(__file__)',os.path.abspath(__file__) print 'realpath(__file__)',os.path.realpath(__file__) |
执行将打印绝对路径,如下所示:
1 2 | abspath(__file__) /home/user/file_test_link realpath(__file__) /home/user/file_test.py |
文件导入测试链接->文件导入测试.py
使用检查@SummerBreeze提到使用检查模块。
对于导入的模块来说,这似乎很好,而且非常简洁:
1 2 3 | import os import inspect print 'inspect.getfile(os) is:', inspect.getfile(os) |
顺服地返回绝对路径。但是,为了找到当前正在执行的脚本的路径,我没有找到使用它的方法。
我不明白为什么没有人在谈论这个,但对我来说,最简单的解决方案是使用imp.find_模块("modulename")(这里的文档):
1 2 | import imp imp.find_module("os") |
它给出一个路径位于第二个位置的元组:
1 2 3 | (<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>, '/usr/lib/python2.7/os.py', ('.py', 'U', 1)) |
与"inspect"方法相比,此方法的优点是不需要导入模块来使其正常工作,并且可以在输入中使用字符串。例如,检查在另一个脚本中调用的模块时很有用。
编辑:
在python3中,
Return the spec for the specified module.
First, sys.modules is checked to see if the module was already imported. If so, then sys.modules[name].spec is returned. If that happens to be
set to None, then ValueError is raised. If the module is not in
sys.modules, then sys.meta_path is searched for a suitable spec with the
value of 'path' given to the finders. None is returned if no spec could
be found.If the name is for submodule (contains a dot), the parent module is
automatically imported.The name and package arguments work the same as importlib.import_module().
In other words, relative module names (with leading dots) work.
这是微不足道的。
每个模块都有一个
因此,获取模块通知它的目录很简单,如下所示:
1 | os.path.dirname(__file__) |
1 2 3 | import os path = os.path.abspath(__file__) dir_path = os.path.dirname(path) |
命令行实用程序
您可以将其调整为命令行实用程序,
1 | python-which <package name> |
创建
1 2 3 4 5 6 7 8 9 10 | #!/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__) |
使其可执行
1 | sudo chmod +x /usr/local/bin/python-which |
1 2 | import module print module.__path__ |
Packages support one more special attribute,
__path__ . This is
initialized to be a list containing the name of the directory holding
the package’s__init__.py before the code in that file is executed.
This variable can be modified; doing so affects future searches for
modules and subpackages contained in the package.While this feature is not often needed, it can be used to extend the
set of modules found in a package.
来源
所以我花了相当多的时间和Py2Exe一起做这个问题是获取脚本的基本文件夹,无论它是作为Python脚本还是作为py2exe可执行文件运行。另外,无论是从当前文件夹、另一个文件夹还是从系统路径运行(这是最困难的),都可以让它工作。
最后,我使用了这种方法,使用sys.frozed作为在py2exe中运行的指示器:
1 2 3 4 5 | 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__)) |
您可以直接导入模块然后点击它的名字,你就会得到它的完整路径。
1 2 3 4 | >>> import os >>> os <module 'os' from 'C:\\Users\\Hassan Ashraf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\os.py'> >>> |
如果使用
1 2 3 4 | import os.path mydir = os.path.dirname(__file__) or '.' full = os.path.abspath(mydir) print __file__, mydir, full |
结果:
1 2 | $ python teste.py teste.py . /home/user/work/teste |
诀窍是在
因此,使用
我想为一个常见的场景(在Python3中)做出贡献,并探索一些方法。
内置函数open()接受相对路径或绝对路径作为其第一个参数。虽然相对路径被视为相对于当前工作目录,但建议将绝对路径传递给文件。
简单地说,如果使用以下代码运行脚本文件,则不能保证将在脚本文件所在的同一目录中创建
1 2 | with open('example.txt', 'w'): pass |
要修复此代码,我们需要获取脚本的路径并使其绝对化。为了确保路径是绝对的,我们只需使用os.path.realpath()函数。要获取脚本的路径,有几个常见的函数返回各种路径结果:
os.getcwd() os.path.realpath('example.txt') sys.argv[0] __file__
两个函数os.getcwd()和os.path.realpath()都基于当前工作目录返回路径结果。通常不是我们想要的。sys.argv list的第一个元素是根脚本(运行的脚本)的路径,而不管您是在根脚本本身还是在其任何模块中调用该列表。在某些情况下,它可能很有用。_uuu file_uuu变量包含调用模块的路径。
以下代码在脚本所在的同一目录中正确创建了文件
1 2 3 4 5 | filedir = os.path.dirname(os.path.realpath(__file__)) filepath = os.path.join(filedir, 'example.txt') with open(filepath, 'w'): pass |
从一个python包的模块中,我必须引用一个与包位于同一目录中的文件。前任。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
因此在上面,我必须从我的_lib_a.py模块调用maincli.py,因为知道top_包和maincli.py在同一目录中。以下是我获取maincli.py路径的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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发布的基础上,我修改了代码。
如果希望从脚本中了解绝对路径,可以使用路径对象:
1 2 3 4 5 | from pathlib import Path print(Path().absolute()) print(Path().resolve('.')) print(Path().cwd()) |
CWD()方法
Return a new path object representing the current directory (as returned by os.getcwd())
resolve()方法
Make the path absolute, resolving any symlinks. A new path object is returned:
如果要在"程序"中动态执行此操作,请尝试以下代码:我的观点是,你可能不知道模块的确切名称来"硬编码"它。它可能是从列表中选择的,也可能不是当前正在运行以使用文件。
(我知道,它在python 3中不起作用)
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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+" ") f.write("modpath ="+modname+" ") f.close() #Call the file with execfile() execfile('modname.py') print modpath <module 'os' from 'C:\Python27\lib\os.pyc'> |
我试图摆脱"全球性"问题,但发现了一些不起作用的案例我认为"execfile()"可以在python 3中模拟因为它在程序中,所以可以很容易地放入方法或模块中以便重用。
如果您想从包的任何模块中检索包的根路径,那么以下方法可以工作(在Python3.6上测试):
1 2 | from . import __path__ as ROOT_PATH print(ROOT_PATH) |
也可以使用
希望这有帮助!