subprocess.Popen(..).communicate(..) 与 graphviz 一起使用时随机丢弃数据!
我正在使用graphviz的dot工具为一个网页应用生成一些svg图表。我是通过Popen来调用dot的:
p = subprocess.Popen(u'/usr/bin/dot -Kfdp -Tsvg', shell=True,\
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
str = u'long-unicode-string-i-want-to-convert'
(stdout,stderr) = p.communicate(str)
结果是,dot程序会抛出一些错误,比如:
Error: not well-formed (invalid token) in line 1
... <tr><td cellpadding="4bgcolor="#EEE8AA"> ...
in label of node n260
这个明显的错误肯定不是因为输入字符串的问题。特别是,如果我把它用utf-8编码保存到str.txt文件中,然后执行:
/usr/bin/dot -Kfdp -Tsvg < str.txt > myimg.svg
我就能得到想要的输出。这个str的“特别”之处在于,它包含像丹麦语中的ø、æ、å这样的字符。
现在我完全不知道该怎么办。问题可能出在dot上;但看起来是因为Popen的使用方式和在命令行中用<符号的方式不同,而我不知道从哪里入手。如果有任何帮助或其他调用dot的方法(除了把所有数据写入文件再调用!)我会非常感激!
1 个回答
3
听起来你应该这样做:
stdout, stderr = p.communicate(str.encode('utf-8'))
(当然,你不应该覆盖内置的 str
。)在Python中,unicode类型是用来存储unicode数据的,而不是UTF-8。如果你想要UTF-8格式的数据,你需要明确地进行编码。
另外,在这个代码片段中使用 shell=True
是没有必要的,传递unicode字面量给subprocess.Popen也不是个好主意(反正它最后会被编码成ASCII)。而且,行末的反斜杠也是多余的——Python知道这一行还没结束,因为你有一个没有关闭的括号。所以,使用:
p = subprocess.Popen(['/usr/bin/dot', '-Kfdp', '-Tsvg'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)