使用Python3 subprocess.Popen调用Prometheus报错:No such file or directory
问题描述
使用Python3的subprocess.Popen调用Prometheus时,始终报错No such file or directory,但在脚本所在目录直接执行./prometheus --help完全正常,且脚本调用node_export也无问题。
代码如下:
if __name__ == '__main__': subprocess.Popen(["pwd"]) rs = subprocess.Popen(["./prometheus", "--help"])
错误信息:
Traceback (most recent call last): File "xxxe/integration_test/test.py", line 33, in <module> rs = subprocess.Popen(["./prometheus", "--help"]) File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/subprocess.py", line 951, in __init__ self._execute_child(args, executable, preexec_fn, close_fds, File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/subprocess.py", line 1821, in _execute_child raise child_exception_type(errno_num, err_msg, err_filename) FileNotFoundError: [Errno 2] No such file or directory: './prometheus'
直接执行命令的结果:
(venv) ➜ integration_test ./prometheus --help usage: prometheus [<flags>] The Prometheus monitoring server Flags: -h, --[no-]help Show context-sensitive help (also try --help-long and --help-man). --[no-]version Show application version. ....
问题分析与解决
核心原因
subprocess.Popen使用相对路径时,依赖的是Python脚本的当前工作目录,而非脚本文件本身所在的目录。你直接在脚本目录执行命令时,工作目录就是该目录,但如果从其他路径启动脚本、或IDE默认工作目录不是脚本所在目录,就会找不到./prometheus。
另外,你执行的subprocess.Popen(["pwd"])不会直接输出结果到控制台,导致你无法直观看到当前工作目录,容易误以为工作目录是脚本所在目录。
解决方法
方法1:用脚本所在目录的绝对路径调用Prometheus
先获取脚本文件的绝对路径,再拼接Prometheus的路径,彻底避免工作目录问题:
import os import subprocess if __name__ == '__main__': # 获取脚本所在目录的绝对路径 script_dir = os.path.dirname(os.path.abspath(__file__)) # 拼接prometheus的绝对路径 prometheus_path = os.path.join(script_dir, "prometheus") rs = subprocess.Popen([prometheus_path, "--help"])
方法2:先切换工作目录到脚本所在目录
在调用Popen前,主动切换工作目录到脚本所在路径,之后再用相对路径调用:
import os import subprocess if __name__ == '__main__': script_dir = os.path.dirname(os.path.abspath(__file__)) # 切换工作目录到脚本所在路径 os.chdir(script_dir) # 此时相对路径会正确指向目标文件 rs = subprocess.Popen(["./prometheus", "--help"])
方法3:调试查看当前工作目录
如果不确定当前工作目录,可以用以下代码打印出来,辅助排查:
import os import subprocess if __name__ == '__main__': print("当前工作目录:", os.getcwd()) # 用subprocess执行pwd并捕获输出 result = subprocess.run(["pwd"], capture_output=True, text=True) print("subprocess的pwd输出:", result.stdout.strip())
至于调用node_export正常,大概率是因为它的调用路径是绝对路径、或者它在系统PATH环境变量中,不受工作目录变化影响,而Prometheus用相对路径且工作目录不匹配才导致报错。
内容的提问来源于stack exchange,提问作者Baker X
相关产品推荐
相关产品推荐

