在 Windows 上,如何使用 Python 2.7 子进程保护 shell 脚本的参数?

发布于 2024-10-17 12:03:03 字数 290 浏览 2 评论 0原文

例如,考虑以下 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南城追梦 2024-10-24 12:03:03

Windows 上的子进程模块,如果给 call 方法提供参数列表使用 “nofollow”>list2cmdline 函数。在这个函数的文档字符串中可以读到:

3) 前面有反斜杠的双引号被解释为
文字双引号。

根据这个,你的问题的解决方案应该是这样的

subprocess.call([r'.\tst.bat', r'\"1|2\"'])

但是,list2cmdline函数的文档和实现之间似乎不匹配;

Python 2.7.4 (default, Apr  6 2013, 19:55:15) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> print subprocess.list2cmdline([r'\"1|2\"'])
\\\"1|2\\\"

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 将每个参数用双引号括起来,里面有一个空格或制表符。如果参数末尾有空格不会破坏批处理文件,您可以在末尾添加它,强制根据需要使用双引号。

>>> import subprocess
>>> print subprocess.list2cmdline(['1|2 '])
"1|2 "

Subprocess module on Windows in case of a list of arguments given to the call method transforms this list into a string using list2cmdline function. In the docstring of this function one can read:

3) A double quotation mark preceded by a backslash is interpreted as a
literal double quotation mark.

According to this the solution of your problem should look like this

subprocess.call([r'.\tst.bat', r'\"1|2\"'])

However it seems like there's a mismatch between documentation and implementation of list2cmdline function;

Python 2.7.4 (default, Apr  6 2013, 19:55:15) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> print subprocess.list2cmdline([r'\"1|2\"'])
\\\"1|2\\\"

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 by list2cmdline 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 - to subprocess.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.

>>> import subprocess
>>> print subprocess.list2cmdline(['1|2 '])
"1|2 "
空城旧梦 2024-10-24 12:03:03

此问题(或类似问题)已被报告为错误。

参考文献:

This (or a similar problem) has been reported as a bug.

References:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文