我想知道在Python中确定当前脚本目录的最佳方法是什么。
我发现,由于调用Python代码的方法很多,很难找到一个好的解决方案。
以下是一些问题:
如果脚本使用exec, execfile执行,则__file__未定义
__module__只在模块中定义
用例:
。/ myfile.py
python myfile.py
/ somedir / myfile.py
python somedir / myfile.py
Execfile ('myfile.py')(来自另一个脚本,可以位于另一个目录,并且可以有另一个当前目录。
我知道没有完美的解决方案,但我正在寻找解决大多数情况的最佳方法。
最常用的方法是os.path.dirname(os.path.abspath(__file__)),但如果你用exec()从另一个脚本执行脚本,这就行不通了。
警告
任何使用当前目录的解决方案都会失败,这可以根据脚本调用的方式有所不同,也可以在运行的脚本中更改。
在Python 3.4+中,你可以使用更简单的pathlib模块:
from inspect import currentframe, getframeinfo
from pathlib import Path
filename = getframeinfo(currentframe()).filename
parent = Path(filename).resolve().parent
你也可以使用__file__(当它可用时)来完全避免inspect模块:
from pathlib import Path
parent = Path(__file__).resolve().parent
#!/usr/bin/env python
import inspect
import os
import sys
def get_script_dir(follow_symlinks=True):
if getattr(sys, 'frozen', False): # py2exe, PyInstaller, cx_Freeze
path = os.path.abspath(sys.executable)
else:
path = inspect.getabsfile(get_script_dir)
if follow_symlinks:
path = os.path.realpath(path)
return os.path.dirname(path)
print(get_script_dir())
It works on CPython, Jython, Pypy. It works if the script is executed using execfile() (sys.argv[0] and __file__ -based solutions would fail here). It works if the script is inside an executable zip file (/an egg). It works if the script is "imported" (PYTHONPATH=/path/to/library.zip python -mscript_to_run) from a zip file; it returns the archive path in this case. It works if the script is compiled into a standalone executable (sys.frozen). It works for symlinks (realpath eliminates symbolic links). It works in an interactive interpreter; it returns the current working directory in this case.
这是一个部分的解决方案,仍然比迄今为止发表的所有解决方案都要好。
import sys, os, os.path, inspect
#os.chdir("..")
if '__file__' not in locals():
__file__ = inspect.getframeinfo(inspect.currentframe())[0]
print os.path.dirname(os.path.abspath(__file__))
现在,这种工作将所有调用,但如果有人使用chdir()来改变当前目录,这也将失败。
注:
sys。Argv[0]不能工作,如果你使用python -c "execfile('path-tester.py')"执行脚本,将返回-c "
我在https://gist.github.com/1385555上发布了完整的测试,欢迎您对其进行改进。