我正在编写一个需要使用subprocess
模块调用外部命令的脚本。问题是我需要将用户提供的文件传递给命令,使其看起来像这样:
p = subprocess.run("command arg1 arg2 {userfile}".format(userfile=f),
capture_output=True, text=True, shell=True)
我必须用shell=True
运行命令才能使其工作,这就是为什么我将命令作为字符串而不是列表传递的原因。
问题是有人可能会传递一个名为:somefile && rm -rf ~
的文件,这是一个出于奇怪原因的无效文件名(至少在Windows上,不知道Mac/Linux),然后坏事发生了。
因此,我需要在将用户输入传递给 shell 之前对其进行转义。我想为此使用内置的shlex.quote
函数,所以通过上面的例子,我得到:'somefile && rm -rf ~'
命令变为:command arg1 arg2 'somefile && rm -rf ~cmd'
应该在 unix 系统上工作。问题是这种转义在带有命令提示符的窗口上不起作用,所以我的脚本在我的窗口机器上失败。
是否有内置或第三方函数/库可以针对所有平台或至少对于 Windows 正确转义命令行参数(因为shlex.quote
适用于 unix)?
我正在 Windows 上开发,所以我需要这个脚本在这个平台上工作,而且我认为像"{userfile}"
这样的东西还不够好。
任何适用于python 3的解决方案将不胜感激。
将列表传递给子进程,例如
p = subprocess.run(["command", "arg1", "arg2" , f],
capture_output=True, text=True)
关于窗口的更新
使用预期二进制文件的绝对路径通常是最佳方法,将命令更改为:
p = subprocess.run(["C:\path\to\binary.exe", "arg1", "arg2" , f],
capture_output=True, text=True)
如果绝对路径未知,那么which
可以用来查找你的二进制文件(在最新版本的Windows上,我在Windows 7上测试过)。
>>> p = subprocess.run(["which", "python"], stdout=subprocess.PIPE)
>>> python_binary = p.stdout.strip().decode() # Convert back to str
>>> python_binary
'C:\Program Files\Python36\python.exe'