我得到了 python 2.6,它有一个旧版本的 toprettyxml() ,它不能按预期进行 xml 格式化。因此我尝试使用子进程调用 xmllint。这是我的简化代码。
xmlParseCmd = "xmllint -format - <<< '%s'" % '<?xml version="1.0" encoding="UTF-8"?> <insertion> <mytag>123456</mytag> <mytag2>789</mytag2> </insertion>'
print shlex.split(xmlParseCmd)
pxmlParser = subprocess.Popen(shlex.split(xmlParseCmd), stdout=subprocess.PIPE)
pretty_xml = pxmlParser.communicate()[0]
print pretty_xml
程序在以下输出后无限期挂起。我猜它正在等待一些输入。
-> python ~/myscripts/resources/test_xtract.py
['xmllint', '-format', '-', '<<<', '<?xml version="1.0" encoding="UTF-8"?> <insertion> <mytag>123456</mytag> <mytag2>789</mytag2> </insertion>']
我已经使用了此处的字符串作为 xmllint 的输入,那么为什么它仍在等待输入?我一直在尝试调试这个问题,但没有找到任何具体的方法来解决这个问题。任何指示都会有很大帮助
最佳答案
这里的字符串 <<<
是一个 shell 构造。使用 shlex()
时,命令行将被分成参数,就像 shell 在那里一样,因此您不需要 shell=True
,但 shlex
不会(也不可能)知道您尝试解析的内容是否是仍然需要 shell....这当然正是这里的问题。
如果你真的很绝望,你当然可以调用 shell 来简单地打印一个字符串(在这种情况下,取出 shlex
并用 shell=True
传递长字符串),但是,你知道,Python也能做到这一点。
from subprocess import run, PIPE
xml = '<?xml version="1.0" encoding="UTF-8"?> <insertion> <mytag>123456</mytag> <mytag2>789</mytag2> </insertion>'
xmllint = run(['xmllint', '-format', '-'], input=xml, stdout=PIPE, universal_newlines=True)
print(xmllint.stdout)
使用这个简单的静态命令,shlex
有点矫枉过正,尽管它当然可以让您免于弄清楚 shell 将如何解析命令行。我只是在这里硬编码了命令。
如果您确实坚持使用 Python 2,请考虑切换到 2.7,它的 subprocess.check_output()
可以做几乎相同的事情,尽管界面有点笨拙。
如果您真的坚持使用 Python 2.6,那么直接与 Popen()
交互,该过程将与您现有的代码非常相似 - 您只需更改它以使用 p = Popen(['xmllint', etc]); p.communicate('string')
传递输入,或者陷入困境Popen("xmllint etc <<<'%s'" % string, shell=True)
的罪恶诱惑(尽管在后一种情况下,没有 shlex
,您必须考虑如何转义输入字符串中的任何单引号,或者接受它们会导致语法错误的事实,所以也许诱惑是当第一个替代方案更加清晰和简单时,这里的效果不是很强)。
关于python:使用 xmllint 时子进程通信无限期等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47830301/