在 Windows 上,如何使用 Python 2.7 子进程保护 shell 脚本的参数?
例如,考虑以下 Python 代码:
subprocess.call([r'.\tst.bat', '"1|2"'])
这里我在 tst.bat 的参数两边加上了双引号,以保护“|”从 shell 中,因为 tst.bat 最终将通过 Windows shell 运行。但是,如果参数中有双引号,Python 2.7 中的 subprocess 会对它们进行转义。结果是 tst.bat 收到这个参数:“1|2”。
如何转义参数“1|2”,以便将其不经转换地传递给 tst.bat?
Consider for example the following Python code:
subprocess.call([r'.\tst.bat', '"1|2"'])
Here I've put double quotes around the argument to tst.bat, in order to protect '|' from the shell since tst.bat will ultimately be run via the Windows shell. However, if there are double quotes in arguments, subprocess in Python 2.7 escapes them. The result is that tst.bat receives this argument: \"1|2\".
How can I escape the argument "1|2" so that it's passed untransformed to tst.bat?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Windows 上的子进程模块,如果给
call
方法提供参数列表使用 “nofollow”>list2cmdline
函数。在这个函数的文档字符串中可以读到:根据这个,你的问题的解决方案应该是这样的
但是,
list2cmdline
函数的文档和实现之间似乎不匹配;Python 3.3.1 中也有相同的行为。
我在 http://bugs.python.org/issue18649
更新
事实证明,我对
list2cmdline
函数的非常具有误导性的文档字符串感到困惑 - 请参阅 http:// bugs.python.org/issue18649 了解详细信息。传递给
subprocess.call
的参数序列由list2cmdline
函数翻译,该函数仅涉及 MS C 运行时使用的引用机制,而不涉及 cmd 使用的引用机制。 EXE文件。这使得将参数(稍后由 cmd.exe 解释)作为列表传递给subprocess.call
变得非常尴尬或不可能。不过,在这种情况下,还有一次让它发挥作用的机会。
list2cmdline
将每个参数用双引号括起来,里面有一个空格或制表符。如果参数末尾有空格不会破坏批处理文件,您可以在末尾添加它,强制根据需要使用双引号。Subprocess module on Windows in case of a list of arguments given to the
call
method transforms this list into a string usinglist2cmdline
function. In the docstring of this function one can read:According to this the solution of your problem should look like this
However it seems like there's a mismatch between documentation and implementation of
list2cmdline
function;The same behavior is in Python 3.3.1.
I raised a bug at http://bugs.python.org/issue18649
UPDATE
It turns out I was confused by very misleading docstring of
list2cmdline
function - see http://bugs.python.org/issue18649 for details.The sequence of arguments passed to
subprocess.call
is translated bylist2cmdline
function which is concerned only with the quoting mechanism used by MS C runtime and not by quoting mechanism used by cmd.exe. This makes passing arguments - which are later to be interpreted by cmd.exe - tosubprocess.call
as a list either very awkward or impossible.There's one more chance to get it working in this case, though.
list2cmdline
double quotes every argument with a space or tab inside. If having a space at the end of your argument does not break the batch file you can add it at the end forcing double quoting as you wanted.此问题(或类似问题)已被报告为错误。
参考文献:
This (or a similar problem) has been reported as a bug.
References: