如何在python中检索模块的路径?
#1 楼
import a_module
print(a_module.__file__)
实际上至少会在Mac OS X上为您提供已加载的.pyc文件的路径。所以我想您可以这样做:
import os
path = os.path.abspath(a_module.__file__)
您也可以尝试:
path = os.path.dirname(a_module.__file__)
获取模块的目录。
评论
这回答了如何获取所导入模块的路径,而不是所处模块/脚本的路径(对于正在运行的脚本,__ file__不是完整路径,它是相对路径)。对于我所在的文件,我必须从同一目录中导入另一个模块,然后执行此处所示的操作。有人知道更方便的方法吗?
–本·布莱恩特
2012年1月19日18:11
@hbdgaf很确定没有内置的东西。__file__
–丹·帕萨罗(Dan Passaro)
13年5月5日在21:24
@BenBryant @hbdgaf os.path.dirname(__ file__)对我来说工作正常,并返回模块目录的abs路径。
–Niccolò
14年8月18日在16:14
我尝试这样做并得到了回溯:AttributeError:'模块'对象没有属性'__file__'
–多里安·多尔(Dorian Dore)
2015年4月5日在17:02
@DorianDore我有点弄乱了模块,并得到了一个解决方案路径= module .__ path __.__ dict __ [“ _ path”] [0],但是我不确定它是否可移植,或者在两个python版本之间是否没有区别。它对我有用,不像这个答案会给我同样的错误,并且检查答案会引发TypeError:
–杰索
16年7月4日在0:15
#2 楼
python中有inspect
模块。官方文档
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获得当前文件的名称。参见stackoverflow.com/a/50905/320036
–z0r
2013年9月24日4:57在
我在这个问题上搜索了很多遍,这是我见过的最合理的答案!请更新有关inspect.currentframe()的信息
–erikbwork
2013年12月18日上午11:15
inspect.getfile()方法不适用于模块_io,但适用于模块io。
–smwikipedia
2014年10月6日,下午1:28
#3 楼
正如其他答案所言,最好的方法是使用__file__
(下面再次说明)。但是,有一个重要警告,那就是如果您单独运行模块(例如__file__
),则__main__
不存在。例如,假设您有两个文件(两个文件都在您的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
>希望这会有所帮助。在测试提出的其他解决方案时,这一警告使我花费了大量时间和困惑。
评论
在这种情况下,可以使用sys.argv [0]代替文件。
–吉莫西
13年2月14日在17:41
这是特定于版本的警告吗?在2.6和2.7中,我成功依赖于文件,当name __ =='__ main'时,该文件有效。我看到的唯一失败案例是“ python -c'打印文件'”。我要补充一点,有时文件可以是“
– Paul Du Bois
13年2月19日在21:23
请注意,前导和尾随的“ __”字符以粗体显示一个单词,因此在阅读前面的注释时请记住这一点:-P
– Paul Du Bois
13年2月19日在21:24
@PaulDuBois您可以使用反斜线包围它:`__file__`变成__file__
– fncomp
2013年3月30日20:30
您如何获得NameError? @Paul Du Bois:我已经尝试使用Python 2.3-3.4并定义了__file__,但是我运行Python文件:python a.py,python -ma,./a.py。
– jfs
2014年2月21日在13:37
#4 楼
我还将尝试解决此问题的一些变体:查找被调用脚本的路径
查找当前正在执行的脚本的路径
查找被调用的目录脚本
(其中一些问题已在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.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)
乖乖地返回绝对路径。要查找当前正在执行的脚本的路径:
inspect.getfile(inspect.currentframe())
(感谢@jbochi)
评论
inspect.getfile(os)与以下代码中的os .__ file__相同:def getfile(object):“”“找出在其中定义对象的源文件或编译文件。”“”如果ismodule(object):如果hasattr (对象,“文件”):返回对象。__file__
– idanzalz
2014年7月8日在12:28
这应该是公认的答案。感谢您提供详尽的答案。
– YSC
11月2日,16:04
#5 楼
我不明白为什么没有人在谈论这个,但是对我来说,最简单的解决方案是使用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
模块应执行以下操作:importlib.util.find_spec
的文档:返回指定模块的规格。
首先,检查sys.modules以确定该模块是否已导入。如果是这样,则返回sys.modules [name] .spec。如果碰巧将其设置为“无”,则会引发ValueError。如果模块不在sys.modules中,则在sys.meta_path中搜索给定查找者的'path'值为
合适的规范。如果找不到任何规范,则不会返回任何内容。
如果名称是子模块的名称(包含点),则会自动导入父模块。
name和package参数的作用与importlib.import_module()相同。
换句话说,相对模块名称(带前导点)起作用。
评论
imp在python 2(当前版本2.7.13)中不被贬值。自3.4起,imp在python 3中已贬值。 importlib应该在python 3中使用。我喜欢这个解决方案,因为它甚至可以在实际导入失败时起作用(例如,因为32位引擎使用64位模块)
–mdew
16 Dec 21在7:57
当尝试找到64位sqlite3的路径并导入失败时,这确实非常好。完善。
–rahvin_t
18/12/7在20:49
importlib.machinery.PathFinder()。find_module(“ os”)。get_filename()我在Python3 +中找到的imp.find_module的最短替代方案。如果有人在寻找importlib.util.find_spec的用法。
–特克斯
19年3月24日在16:10
此方法无需导入实际模块即可工作,这非常好,因为我使用它来确定要从共享计算机导入哪个版本的模块。
–高达
19年5月9日在7:07
#6 楼
这很简单。每个模块都有一个
__file__
变量,该变量显示当前位置的相对路径。因此,获取模块通知目录是简单为:
os.path.dirname(__file__)
评论
几乎但不太正确-文件不是“相对于您现在所在的位置”;当它是相对的(仅当sys.path中存在相对路径时),才是相对于模块加载时的位置。
–查尔斯·达菲(Charles Duffy)
08-10-29在19:25
从Python 3.9开始__file__始终是绝对路径。
–鲍里斯(Boris)
10月6日,下午3:16
#7 楼
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
评论
由于__file__只是dir / test.py,因此在我的Linux python 2.6上不起作用,abspath涉及cwd来完成路径名,这不是期望的结果,但是如果您导入模块,则m .__ file__会给出期望的结果。
–本·布莱恩特
2012年1月19日17:41
#8 楼
import module
print module.__path__
软件包还支持另一个特殊属性
__path__
。 初始化为包含目录的名称的列表,该目录在执行该文件中的代码之前保存软件包的
__init__.py
。该变量可以修改;这样做会影响以后对包中包含的模块和子包的搜索。
虽然此功能并不经常需要,但可用于扩展在模块中找到的模块组。一个包装。
来源
#9 楼
命令行实用程序您可以将其调整为命令行实用程序,
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
#10 楼
您只需导入模块,然后按其名称即可获得其完整路径
>>> import os
>>> os
<module 'os' from 'C:\Users\Hassan Ashraf\AppData\Local\Programs\Python\Python36-32\lib\os.py'>
>>>
#11 楼
因此,我花了大量时间尝试使用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__))
#12 楼
如果您想从脚本中知道绝对路径,则可以使用Path对象:from pathlib import Path
print(Path().absolute())
print(Path().resolve('.'))
print(Path().cwd())
cwd()方法
返回代表当前目录的新路径对象(由os.getcwd()返回)
resolve()方法
进行路径绝对,解决任何符号链接。返回一个新的路径对象:
#13 楼
如果要从其任何模块中检索软件包的根路径,请执行以下工作(在Python 3.6上测试):from . import __path__ as ROOT_PATH
print(ROOT_PATH)
也可以引用主要
__init__.py
路径通过使用__file__
代替。希望有帮助!
#14 楼
如果使用__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()
呼叫。它将目录设置为.
,这意味着当前目录,并且是任何与路径相关的功能的有效目录。因此,并不需要真正使用
abspath()
。但是,如果仍然使用它,就不需要技巧了:abspath()
接受空白路径并将其正确解释为当前目录。评论
更好地交换顺序,只使用os.path.dirname(os.path.abspath(__ file__)),因为那样您根本不必担心相对路径。一个更少的错误机会。
– szali
2月3日8:35
#15 楼
我想为一个常见的场景(在Python 3中)做出贡献,并探索一些解决方法。内置函数open()接受相对路径或绝对路径作为其第一个参数。尽管相对路径被视为相对于当前工作目录的相对路径,所以建议将绝对路径传递给该文件。
简单地说,如果使用以下代码运行脚本文件,则不保证将在脚本文件所在的目录中创建
example.txt
文件: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列表的第一个元素是根脚本(运行的脚本)的路径,无论您是在根脚本本身还是在其任何模块中调用列表。在某些情况下可能会派上用场。 __file__变量包含调用它的模块的路径。
以下代码在脚本所在的目录中正确创建了文件
example.txt
:filedir = os.path.dirname(os.path.realpath(__file__))
filepath = os.path.join(filedir, 'example.txt')
with open(filepath, 'w'):
pass
#16 楼
从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的发布,我修改了代码。
#17 楼
如果您希望在“程序”中动态执行此操作,请尝试以下代码:我的意思是,您可能不知道要对其进行“硬编码”的模块的确切名称。
它可以从列出或当前可能无法运行以使用__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中进行仿真
由于这是在程序中,因此可以很容易地将其放入在可重用的方法或模块中。
#18 楼
导入模块时,您可以访问大量信息。签出dir(a_module)
。至于路径,有一个小题为: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'>
#19 楼
如果使用pip安装了它,则“ pip show”效果很好(“位置”)$ pip show detectron2
Name: detectron2
Version: 0.1
Summary: Detectron2 is FAIR next-generation research platform for object detection and segmentation.
Home-page: https://github.com/facebookresearch/detectron2
Author: FAIR
Author-email: None
License: UNKNOWN
Location: /home/ubuntu/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages
Requires: yacs, tabulate, tqdm, pydot, tensorboard, Pillow, termcolor, future, cloudpickle, matplotlib, fvcore
#20 楼
这是一个快速的bash脚本,以防对任何人有用。我只想能够设置一个环境变量,以便可以对代码进行编码。#!/bin/bash
module=${1:?"I need a module name"}
python << EOI
import $module
import os
print os.path.dirname($module.__file__)
EOI
Shell示例:
[root@sri-4625-0004 ~]# export LXML=$(get_python_path.sh lxml)
[root@sri-4625-0004 ~]# echo $LXML
/usr/lib64/python2.7/site-packages/lxml
[root@sri-4625-0004 ~]#
评论
检出modulefinder:docs.python.org/library/modulefinder.html如果您仍在此站点上查找,请更新对此的正确答案。它比建议的解决方案更干净,并且在未设置__file__的情况下也可以使用。
@ erikb85:它不仅更清洁;当__file__默默产生错误名称时,基于检查的解决方案也适用于execfile()情况。
相关:如何在Python中正确确定当前脚本目录?
导入pathlib,模块; pathlib.Path(module .__ file __)。resolve()。parent这是平台无关的