我想知道在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()从另一个脚本执行脚本,这就行不通了。

警告

任何使用当前目录的解决方案都会失败,这可以根据脚本调用的方式有所不同,也可以在运行的脚本中更改。


当前回答

希望这有助于:- 如果你在任何地方运行一个脚本/模块,你将能够访问__file__变量,这是一个表示脚本位置的模块变量。

另一方面,如果你正在使用解释器,你不能访问这个变量,在那里你会得到一个名字NameError和os.getcwd()会给你错误的目录,如果你从其他地方运行文件。

这个解决方案应该会在所有情况下给你你想要的:

from inspect import getsourcefile
from os.path import abspath
abspath(getsourcefile(lambda:0))

我还没有彻底测试,但它解决了我的问题。

其他回答

import os
cwd = os.getcwd()

做你想做的事?我不确定你说的“当前脚本目录”到底是什么意思。您给出的用例的预期输出是什么?

要获得包含当前脚本的目录的绝对路径,您可以使用:

from pathlib import Path
absDir = Path(__file__).parent.resolve()

请注意,.resolve()调用是必需的,因为它使路径成为绝对路径。如果没有resolve(),您将获得类似于'.'的东西。

这个解决方案使用pathlib,它自v3.4(2014)以来一直是Python的stdlib的一部分。与使用os的其他解决方案相比,这是更可取的。

官方的pathlib文档有一个有用的表,将旧的操作系统函数映射到新函数:https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module

#!/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.

在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

如果__file__可用:

# -- script1.py --
import os
file_path = os.path.abspath(__file__)
print(os.path.dirname(file_path))

对于那些我们希望能够从解释器中运行命令或从你运行脚本的地方获取路径的人:

# -- script2.py --
import os
print(os.path.abspath(''))

这是从解释器开始的。 但是当在脚本中运行(或导入)时,它会给出位置的路径 您运行脚本的路径,而不是目录包含的路径 带有打印的脚本。

例子:

如果您的目录结构为

test_dir (in the home dir)
├── main.py
└── test_subdir
    ├── script1.py
    └── script2.py

with

# -- main.py --
import script1.py
import script2.py

输出结果为:

~/test_dir/test_subdir
~/test_dir