Python 如何正确确定当前脚本目录?
我想看看在Python中确定当前脚本目录的最佳方法是什么 我发现,由于调用Python代码的方法很多,很难找到好的解决方案 以下是一些问题:Python 如何正确确定当前脚本目录?,python,pythonpath,dirname,Python,Pythonpath,Dirname,我想看看在Python中确定当前脚本目录的最佳方法是什么 我发现,由于调用Python代码的方法很多,很难找到好的解决方案 以下是一些问题: 如果脚本是使用exec,execfile执行的,则不定义\uuuuuuuu文件 \uuuuu模块仅在模块中定义 用例: /myfile.py python myfile.py /somedir/myfile.py python somedir/myfile.py execfile('myfile.py')(来自另一个脚本,可以位于另一个目录中,也可以
- 如果脚本是使用
,exec
执行的,则不定义execfile
\uuuuuuuu文件
仅在模块中定义\uuuuu模块
/myfile.py
python myfile.py
/somedir/myfile.py
python somedir/myfile.py
(来自另一个脚本,可以位于另一个目录中,也可以具有另一个当前目录execfile('myfile.py')
os.path.dirname(os.path.abspath(\uu文件\uu))
,但是如果使用exec()
从另一个脚本执行脚本,这实际上不起作用
警告
任何使用当前目录的解决方案都将失败,这可能与调用脚本的方式不同,也可能在正在运行的脚本中更改
import os
cwd = os.getcwd()
做你想做的事?我不确定你所说的“当前脚本目录”到底是什么意思。你给出的用例的预期输出是什么
os.path.dirname(os.path.abspath(__file__))
确实是你能得到的最好的
使用exec
/execfile
执行脚本是不常见的;通常,您应该使用模块基础结构来加载脚本。如果必须使用这些方法,我建议在传递给脚本的全局文件中设置\uuuuuu文件
,以便脚本可以读取该文件名
没有其他方法可以在执行代码中获取文件名:正如您所注意到的,CWD可能位于完全不同的位置。如果您真的想讨论通过execfile(…)
调用脚本的情况,您可以使用inspect
模块推断文件名(包括路径)。据我所知,这将适用于您列出的所有情况:
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
只需使用os.path.dirname(os.path.abspath(_文件__))
并仔细检查是否确实需要使用exec
的情况。如果不能将脚本用作模块,则可能是设计出问题的迹象
请记住Python的Zen#8,如果您认为有一个很好的理由可以证明它必须适用于exec
,那么请让我们了解更多有关问题背景的详细信息。首先..如果我们讨论的是注入匿名代码的方法,这里缺少几个用例
code.compile_command()
code.interact()
imp.load_compiled()
imp.load_dynamic()
imp.load_module()
__builtin__.compile()
loading C compiled shared objects? example: _socket?)
但是,真正的问题是,你的目标是什么——你是在试图实施某种安全性?还是你只是对加载的内容感兴趣
如果您感兴趣,则通过exec/execfile导入的文件名无关紧要-您应该使用,它提供以下功能:
此模块包含RExec类,
它支持r_eval()、r_execfile(),
r_exec()和r_import()方法
是标准的限制版本
Python函数eval()、execfile()和
exec和import语句。代码
在这个受限环境中执行
将只能访问模块和
被认为是安全的功能;您可以
子类RExec根据需要添加或删除功能
想要的
然而,如果这更像是一种学术追求的话……这里有一些愚蠢的方法,你可以
也许能更深入地了解
示例脚本:
/deep.py
print ' >> level 1'
execfile('deeper.py')
print ' << level 1'
print '\t >> level 2'
exec("import sys; sys.path.append('/tmp'); import deepest")
print '\t << level 2'
print '\t\t >> level 3'
print '\t\t\t I can see the earths core.'
print '\t\t << level 3'
import sys, os
def overseer(frame, event, arg):
print "loaded(%s)" % os.path.abspath(frame.f_code.co_filename)
sys.settrace(overseer)
execfile("deep.py")
sys.exit(0)
输出
loaded(/Users/synthesizerpatel/deep.py)
>> level 1
loaded(/Users/synthesizerpatel/deeper.py)
>> level 2
loaded(/Users/synthesizerpatel/<string>)
loaded(/tmp/deepest.py)
>> level 3
I can see the earths core.
<< level 3
<< level 2
<< level 1
已加载(/Users/synthezerpatel/deep.py)
>>一级
已加载(/Users/synthezerpatel/deepher.py)
>>二级
已加载(/Users/synthezerpatel/)
已加载(/tmp/deep.py)
>>三级
我能看到地核。
这是一个局部解决方案,仍然比迄今为止所有已发表的方案都要好
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
- 我在上发布了一个完整的测试,欢迎您改进它
它在CPython、Jython、pypypy上工作。如果脚本是使用execfile()
(sys.argv[0]
和\uuuu文件
执行的,那么它可以工作。如果脚本在内部,那么它可以工作。如果脚本是“导入的”(PYTHONPATH=/path/to/library.zip python-mscript\u-to-run
)从zip文件;在本例中,它返回存档路径。如果脚本被编译成独立的可执行文件(sys.freezed
),它就会工作。它适用于符号链接(realpath
消除符号链接)。它在交互式解释器中工作;在这种情况下,它返回当前工作目录。在大多数情况下,它应该工作:
import os,sys
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
希望这有助于:
如果您从任何地方运行脚本/模块,您都可以访问\uuuu文件\uuuu
变量,该变量是表示脚本位置的模块变量
另一方面,如果您使用的是解释器,您没有访问该变量的权限,您将在其中获得一个名称namererror
和os.getcwd()
如果您从其他地方运行该文件,它将为您提供不正确的目录
在所有情况下,解决方案都应满足您的需求:
from inspect import getsourcefile
from os.path import abspath
abspath(getsourcefile(lambda:0))
我还没有完全测试它,但它解决了我的问题。在Python 3.4+中,您可以使用更简单的模块:
您还可以使用\uuuu文件\uuuu
来避免检查
模块:
从pathlib导入路径
父项=路径(文件)
from inspect import getsourcefile
from os.path import abspath
abspath(getsourcefile(lambda:0))
from inspect import currentframe, getframeinfo
from pathlib import Path
filename = getframeinfo(currentframe()).filename
parent = Path(filename).resolve().parent
from pathlib import Path
script_dir = Path(__file__).parent
$ pip install locate
$ python
>>> from locate import this_dir
>>> print(this_dir())
C:/Users/simon
from pathlib import Path
__dirpath__ = Path(globals().get("__file__", "./_")).absolute().parent
import os
__dirpath__ = os.path.dirname(os.path.abspath(globals().get("__file__", "./_")))
test_dir (in the home dir)
├── main.py
└── test_subdir
├── script1.py
└── script2.py
~/test_dir/test_subdir
~/test_dir
print(__import__("pathlib").Path(__file__).parent)