我有这个功能:
def relative_path(*paths):
return os.path.join(os.path.dirname(__file__), *paths)
我如何更改它以返回相对于来电者的路径?
例如,如果我从另一个脚本调用relative_path('index.html')
,是否可以从隐式调用它的位置获取相对于脚本的路径,或者我是否需要修改relative_path
以传递{{1}像这样??
__file__
答案 0 :(得分:2)
在Get __name__ of calling function's module in Python
中调整解决方案file1.py
import os
import inspect
def relative_path(*paths):
return os.path.join(os.path.dirname(__file__), *paths)
def relative_to_caller(*paths):
frm = inspect.stack()[1]
mod = inspect.getmodule(frm[0])
return os.path.join(os.path.dirname(mod.__file__), *paths)
if __name__ == '__main__':
print(relative_path('index.html'))
子/ sub_file.py
import sys
sys.path.append(r'/Users/xx/PythonScripts/!scratch')
import file1
if __name__ == '__main__':
print(file1.relative_path('index.html'))
print(file1.relative_to_caller('index.html'))
运行sub_file.py会给出以下输出:
/Users/xx/PythonScripts/!scratch/index.html
/Users/xx/PythonScripts/!scratch/sub/index.html
上述链接中的问题评论中有一些注意事项......
答案 1 :(得分:0)
请注意,跟踪堆栈在这里是可能的,但它可能会导致一些严重的麻烦(比如混淆'垃圾收集器',或者甚至可能不能用于鸡蛋)
我认为最干净的方法是将调用者传递给rel_path函数。
然而,正如您所知,在python中通常会有一种丑陋的做法。你可以这样做:
考虑遵循以下两个脚本:
# relpath.py
import os
def rel_path(path):
if os.path.isfile(__name__):
return os.path.relpath(path, start=__name__)
print("Warning: %s is not a file: returning path relative to the current working dir" % __name__, file=sys.stderr)
return os.path.relpath(path)
# caller.py
import importlib.util
spec = importlib.util.spec_from_file_location(name=__file__, location="/workspace/relpath.py")
rel = importlib.util.module_from_spec(spec)
spec.loader.exec_module(rel)
print(rel.rel_path("/tmp"))
我们在这里做了什么:当使用importlib.util加载模块时,我们传递了name=__file__
,它为我们的模块提供了由调用者脚本 path 组成的名称。因此,我们不需要将它作为参数传递给 relpath.py 。
请注意,这是不干净的解决方案,对于将来阅读代码的开发人员来说可能不是可读。我只想展示python的可能性。