This may seem like a newbie question, but it is not. Some common approaches don't work in all cases:
这似乎是一个新手的问题,但事实并非如此。有些常见的方法并非在所有情况下都有效:
sys.argv[0]
This means using path = os.path.abspath(os.path.dirname(sys.argv[0]))
, but this does not work if you are running from another Python script in another directory, and this can happen in real life.
这意味着使用path = os.path.abspath(os.path.dirname(sys.argv[0]))),但是如果您正在另一个目录中的另一个Python脚本中运行,这将不起作用,这在现实生活中可能会发生。
__file__
This means using path = os.path.abspath(os.path.dirname(__file__))
, but I found that this doesn't work:
这意味着使用path = os.path.abspath(os.path.dirname(__file__))),但我发现这行不通:
-
py2exe
doesn't have a__file__
attribute, but there is a workaround - py2exe没有__file__属性,但是有一个解决方案
- When you run from IDLE with
execute()
there is no__file__
attribute - 当您使用execute()从IDLE运行时,没有__file__属性
- OS X 10.6 where I get
NameError: global name '__file__' is not defined
- 在这里我得到了NameError:全局名称“__file__”没有定义。
Related questions with incomplete answers:
回答不完整的相关问题:
- Python - Find Path to File Being Run
- Python -找到正在运行的文件的路径
- Path to current file depends on how I execute the program
- 当前文件的路径取决于我如何执行程序
- How to know the path of the running script in Python?
- 如何知道Python中运行脚本的路径?
- Change directory to the directory of a Python script
- 将目录更改为Python脚本的目录
I'm looking for a generic solution, one that would work in all above use cases.
我正在寻找一个通用的解决方案,一个可以在所有以上用例中工作的解决方案。
Update
Here is the result of a testcase:
下面是一个测试案例的结果:
Output of python a.py (on Windows)
a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz
b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz
a.py
#! /usr/bin/env python
import os, sys
print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print
execfile("subdir/b.py")
subdir/b.py
#! /usr/bin/env python
import os, sys
print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print
tree
C:.
| a.py
\---subdir
b.py
10 个解决方案
#1
76
You can't directly determine the location of the main script being executed. After all, sometimes the script didn't come from a file at all. For example, it could come from the interactive interpreter or dynamically generated code stored only in memory.
您不能直接确定正在执行的主脚本的位置。毕竟,有时候脚本根本不是来自文件。例如,它可以来自交互式解释器或仅存储在内存中的动态生成代码。
However, you can reliably determine the location of a module, since modules are always loaded from a file. If you create a module with the following code and put it in the same directory as your main script, then the main script can import the module and use that to locate itself.
但是,您可以可靠地确定模块的位置,因为模块总是从文件中加载。如果您使用以下代码创建一个模块,并将其放在与主脚本相同的目录中,那么主脚本可以导入该模块并使用它来定位自己。
some_path/module_locator.py:
some_path / module_locator.py:
def we_are_frozen():
# All of the modules are built-in to the interpreter, e.g., by py2exe
return hasattr(sys, "frozen")
def module_path():
encoding = sys.getfilesystemencoding()
if we_are_frozen():
return os.path.dirname(unicode(sys.executable, encoding))
return os.path.dirname(unicode(__file__, encoding))
some_path/main.py:
some_path / main.py:
import module_locator
my_path = module_locator.module_path()
If you have several main scripts in different directories, you may need more than one copy of module_locator.
如果在不同的目录中有多个主脚本,您可能需要多个module_locator副本。
Of course, if your main script is loaded by some other tool that doesn't let you import modules that are co-located with your script, then you're out of luck. In cases like that, the information you're after simply doesn't exist anywhere in your program. Your best bet would be to file a bug with the authors of the tool.
当然,如果您的主脚本被其他一些工具加载,而这些工具不允许您导入与脚本位于同一位置的模块,那么您就不走运了。在这样的情况下,你需要的信息在你的程序中根本不存在。最好的方法是向工具的作者提交一个bug。
#2
45
First, you need to import from inspect
and os
首先,需要从inspect和os导入
from inspect import getsourcefile
from os.path import abspath
Next, wherever you want to find the source file from you just use
接下来,无论您想从哪里找到源文件,只要使用
abspath(getsourcefile(lambda:0))
#3
13
I was running into a similar problem, and I think this might solve the problem:
我遇到了一个类似的问题,我认为这可以解决这个问题:
def module_path(local_function):
''' returns the module path without the use of __file__. Requires a function defined
locally in the module.
from http://*.com/questions/729583/getting-file-path-of-imported-module'''
return os.path.abspath(inspect.getsourcefile(local_function))
It works for regular scripts and in idle. All I can say is try it out for others!
它适用于常规脚本和空闲脚本。我能说的就是为别人尝试一下!
My typical usage:
我的典型的用法:
from toolbox import module_path
def main():
pass # Do stuff
global __modpath__
__modpath__ = module_path(main)
Now I use __modpath__ instead of __file__.
现在我使用__modpath__而不是__file__。
#4
6
The short answer is that there is no guaranteed way to get the information you want, however there are heuristics that work almost always in practice. You might look at How do I find the location of the executable in C?. It discusses the problem from a C point of view, but the proposed solutions are easily transcribed into Python.
简短的回答是,没有保证的方法可以得到您想要的信息,但是有一些启发式几乎总是在实践中起作用。您可以看看如何在C中找到可执行文件的位置。它从C的角度讨论这个问题,但是所提出的解决方案很容易被转录成Python。
#5
3
this solution is robust even in executables
这个解决方案即使在可执行文件中也是健壮的
import inspect, os.path
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
#6
3
See my answer to the question Importing modules from parent folder for related information, including why my answer doesn't use the unreliable __file__
variable. This simple solution should be cross-compatible with different operating systems as the modules os
and inspect
come as part of Python.
有关相关信息,请参见我对从父文件夹导入模块的问题的回答,包括为什么我的答案不使用不可靠的__file__变量。这个简单的解决方案应该与不同的操作系统相互兼容,因为模块os和inspect都是Python的一部分。
First, you need to import parts of the inspect and os modules.
首先,您需要导入检查和操作系统模块的部分。
from inspect import getsourcefile
from os.path import abspath
Next, use the following line anywhere else it's needed in your Python code:
接下来,在您的Python代码中需要的任何地方使用以下行:
abspath(getsourcefile(lambda:0))
How it works:
From the built-in module os
(description below), the abspath
tool is imported.
从内置模块os(下面的描述)中导入abspath工具。
OS routines for Mac, NT, or Posix depending on what system we're on.
Mac、NT或Posix的操作系统例程取决于我们使用的系统。
Then getsourcefile
(description below) is imported from the built-in module inspect
.
然后从内置模块检查导入getsourcefile(下面的描述)。
Get useful information from live Python objects.
从活动的Python对象中获取有用的信息。
-
abspath(path)
returns the absolute/full version of a file path - abspath(path)返回文件路径的绝对/完整版本
-
getsourcefile(lambda:0)
somehow gets the internal source file of the lambda function object, so returns'<pyshell#nn>'
in the Python shell or returns the file path of the Python code currently being executed. -
getsourcefile(lambda:0)以某种方式获取lambda函数对象的内部源文件,因此在Python shell中返回'
',或者返回当前正在执行的Python代码的文件路径。 #nn>
Using abspath
on the result of getsourcefile(lambda:0)
should make sure that the file path generated is the full file path of the Python file.
This explained solution was originally based on code from the answer at How do I get the path of the current executed file in Python?.
在getsourcefile(lambda:0)的结果上使用abspath应该确保生成的文件路径是Python文件的完整文件路径。这个解释的解决方案最初是基于如何在Python中获得当前执行文件的路径的答案的代码。
#7
2
This should do the trick in a cross-platform way (so long as you're not using the interpreter or something):
这应该通过跨平台的方式来实现(只要您不使用解释器或其他东西):
import os, sys
non_symbolic=os.path.realpath(sys.argv[0])
program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))
sys.path[0]
is the directory that your calling script is in (the first place it looks for modules to be used by that script). We can take the name of the file itself off the end of sys.argv[0]
(which is what I did with os.path.basename
). os.path.join
just sticks them together in a cross-platform way. os.path.realpath
just makes sure if we get any symbolic links with different names than the script itself that we still get the real name of the script.
sys。路径[0]是您的调用脚本所在的目录(它首先查找该脚本要使用的模块)。我们可以把文件本身的名称从sys中去掉。argv[0](这就是我对os.path.basename所做的)。os.path。通过跨平台的方式把它们粘在一起。os.path。realpath只确保,如果得到与脚本本身名称不同的符号链接,我们仍然可以得到脚本的真实名称。
I don't have a Mac; so, I haven't tested this on one. Please let me know if it works, as it seems it should. I tested this in Linux (Xubuntu) with Python 3.4. Note that many solutions for this problem don't work on Macs (since I've heard that __file__
is not present on Macs).
我没有Mac;我还没有在一个上测试过。如果可以的话,请告诉我。我在Linux (Xubuntu)中使用Python 3.4测试了这一点。注意,这个问题的许多解决方案都不能在mac上使用(因为我听说__file__不在mac上)。
Note that if your script is a symbolic link, it will give you the path of the file it links to (and not the path of the symbolic link).
注意,如果您的脚本是一个符号链接,它将为您提供它链接到的文件的路径(而不是符号链接的路径)。
#8
2
You can use Path
from the pathlib
module:
可以使用pathlib模块中的路径:
from pathlib import Path
# ...
Path(__file__)
You can use call to parent
to go further in the path:
您可以通过调用父类来在路径中走得更远:
Path(__file__).parent
#9
1
You have simply called:
你干脆叫:
path = os.path.abspath(os.path.dirname(sys.argv[0]))
instead of:
而不是:
path = os.path.dirname(os.path.abspath(sys.argv[0]))
abspath()
gives you the absolute path of sys.argv[0]
(the filename your code is in) and dirname()
returns the directory path without the filename.
abspath()给出了sys的绝对路径。argv[0](代码所在的文件名)和dirname()返回没有文件名的目录路径。
#10
0
Simply add the following:
简单地添加以下:
from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)
Or:
或者:
from sys import *
print(sys.argv[0])
#1
76
You can't directly determine the location of the main script being executed. After all, sometimes the script didn't come from a file at all. For example, it could come from the interactive interpreter or dynamically generated code stored only in memory.
您不能直接确定正在执行的主脚本的位置。毕竟,有时候脚本根本不是来自文件。例如,它可以来自交互式解释器或仅存储在内存中的动态生成代码。
However, you can reliably determine the location of a module, since modules are always loaded from a file. If you create a module with the following code and put it in the same directory as your main script, then the main script can import the module and use that to locate itself.
但是,您可以可靠地确定模块的位置,因为模块总是从文件中加载。如果您使用以下代码创建一个模块,并将其放在与主脚本相同的目录中,那么主脚本可以导入该模块并使用它来定位自己。
some_path/module_locator.py:
some_path / module_locator.py:
def we_are_frozen():
# All of the modules are built-in to the interpreter, e.g., by py2exe
return hasattr(sys, "frozen")
def module_path():
encoding = sys.getfilesystemencoding()
if we_are_frozen():
return os.path.dirname(unicode(sys.executable, encoding))
return os.path.dirname(unicode(__file__, encoding))
some_path/main.py:
some_path / main.py:
import module_locator
my_path = module_locator.module_path()
If you have several main scripts in different directories, you may need more than one copy of module_locator.
如果在不同的目录中有多个主脚本,您可能需要多个module_locator副本。
Of course, if your main script is loaded by some other tool that doesn't let you import modules that are co-located with your script, then you're out of luck. In cases like that, the information you're after simply doesn't exist anywhere in your program. Your best bet would be to file a bug with the authors of the tool.
当然,如果您的主脚本被其他一些工具加载,而这些工具不允许您导入与脚本位于同一位置的模块,那么您就不走运了。在这样的情况下,你需要的信息在你的程序中根本不存在。最好的方法是向工具的作者提交一个bug。
#2
45
First, you need to import from inspect
and os
首先,需要从inspect和os导入
from inspect import getsourcefile
from os.path import abspath
Next, wherever you want to find the source file from you just use
接下来,无论您想从哪里找到源文件,只要使用
abspath(getsourcefile(lambda:0))
#3
13
I was running into a similar problem, and I think this might solve the problem:
我遇到了一个类似的问题,我认为这可以解决这个问题:
def module_path(local_function):
''' returns the module path without the use of __file__. Requires a function defined
locally in the module.
from http://*.com/questions/729583/getting-file-path-of-imported-module'''
return os.path.abspath(inspect.getsourcefile(local_function))
It works for regular scripts and in idle. All I can say is try it out for others!
它适用于常规脚本和空闲脚本。我能说的就是为别人尝试一下!
My typical usage:
我的典型的用法:
from toolbox import module_path
def main():
pass # Do stuff
global __modpath__
__modpath__ = module_path(main)
Now I use __modpath__ instead of __file__.
现在我使用__modpath__而不是__file__。
#4
6
The short answer is that there is no guaranteed way to get the information you want, however there are heuristics that work almost always in practice. You might look at How do I find the location of the executable in C?. It discusses the problem from a C point of view, but the proposed solutions are easily transcribed into Python.
简短的回答是,没有保证的方法可以得到您想要的信息,但是有一些启发式几乎总是在实践中起作用。您可以看看如何在C中找到可执行文件的位置。它从C的角度讨论这个问题,但是所提出的解决方案很容易被转录成Python。
#5
3
this solution is robust even in executables
这个解决方案即使在可执行文件中也是健壮的
import inspect, os.path
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
#6
3
See my answer to the question Importing modules from parent folder for related information, including why my answer doesn't use the unreliable __file__
variable. This simple solution should be cross-compatible with different operating systems as the modules os
and inspect
come as part of Python.
有关相关信息,请参见我对从父文件夹导入模块的问题的回答,包括为什么我的答案不使用不可靠的__file__变量。这个简单的解决方案应该与不同的操作系统相互兼容,因为模块os和inspect都是Python的一部分。
First, you need to import parts of the inspect and os modules.
首先,您需要导入检查和操作系统模块的部分。
from inspect import getsourcefile
from os.path import abspath
Next, use the following line anywhere else it's needed in your Python code:
接下来,在您的Python代码中需要的任何地方使用以下行:
abspath(getsourcefile(lambda:0))
How it works:
From the built-in module os
(description below), the abspath
tool is imported.
从内置模块os(下面的描述)中导入abspath工具。
OS routines for Mac, NT, or Posix depending on what system we're on.
Mac、NT或Posix的操作系统例程取决于我们使用的系统。
Then getsourcefile
(description below) is imported from the built-in module inspect
.
然后从内置模块检查导入getsourcefile(下面的描述)。
Get useful information from live Python objects.
从活动的Python对象中获取有用的信息。
-
abspath(path)
returns the absolute/full version of a file path - abspath(path)返回文件路径的绝对/完整版本
-
getsourcefile(lambda:0)
somehow gets the internal source file of the lambda function object, so returns'<pyshell#nn>'
in the Python shell or returns the file path of the Python code currently being executed. -
getsourcefile(lambda:0)以某种方式获取lambda函数对象的内部源文件,因此在Python shell中返回'
',或者返回当前正在执行的Python代码的文件路径。 #nn>
Using abspath
on the result of getsourcefile(lambda:0)
should make sure that the file path generated is the full file path of the Python file.
This explained solution was originally based on code from the answer at How do I get the path of the current executed file in Python?.
在getsourcefile(lambda:0)的结果上使用abspath应该确保生成的文件路径是Python文件的完整文件路径。这个解释的解决方案最初是基于如何在Python中获得当前执行文件的路径的答案的代码。
#7
2
This should do the trick in a cross-platform way (so long as you're not using the interpreter or something):
这应该通过跨平台的方式来实现(只要您不使用解释器或其他东西):
import os, sys
non_symbolic=os.path.realpath(sys.argv[0])
program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))
sys.path[0]
is the directory that your calling script is in (the first place it looks for modules to be used by that script). We can take the name of the file itself off the end of sys.argv[0]
(which is what I did with os.path.basename
). os.path.join
just sticks them together in a cross-platform way. os.path.realpath
just makes sure if we get any symbolic links with different names than the script itself that we still get the real name of the script.
sys。路径[0]是您的调用脚本所在的目录(它首先查找该脚本要使用的模块)。我们可以把文件本身的名称从sys中去掉。argv[0](这就是我对os.path.basename所做的)。os.path。通过跨平台的方式把它们粘在一起。os.path。realpath只确保,如果得到与脚本本身名称不同的符号链接,我们仍然可以得到脚本的真实名称。
I don't have a Mac; so, I haven't tested this on one. Please let me know if it works, as it seems it should. I tested this in Linux (Xubuntu) with Python 3.4. Note that many solutions for this problem don't work on Macs (since I've heard that __file__
is not present on Macs).
我没有Mac;我还没有在一个上测试过。如果可以的话,请告诉我。我在Linux (Xubuntu)中使用Python 3.4测试了这一点。注意,这个问题的许多解决方案都不能在mac上使用(因为我听说__file__不在mac上)。
Note that if your script is a symbolic link, it will give you the path of the file it links to (and not the path of the symbolic link).
注意,如果您的脚本是一个符号链接,它将为您提供它链接到的文件的路径(而不是符号链接的路径)。
#8
2
You can use Path
from the pathlib
module:
可以使用pathlib模块中的路径:
from pathlib import Path
# ...
Path(__file__)
You can use call to parent
to go further in the path:
您可以通过调用父类来在路径中走得更远:
Path(__file__).parent
#9
1
You have simply called:
你干脆叫:
path = os.path.abspath(os.path.dirname(sys.argv[0]))
instead of:
而不是:
path = os.path.dirname(os.path.abspath(sys.argv[0]))
abspath()
gives you the absolute path of sys.argv[0]
(the filename your code is in) and dirname()
returns the directory path without the filename.
abspath()给出了sys的绝对路径。argv[0](代码所在的文件名)和dirname()返回没有文件名的目录路径。
#10
0
Simply add the following:
简单地添加以下:
from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)
Or:
或者:
from sys import *
print(sys.argv[0])