subprocess.Popen (..). общаться (..) выбрасывать данные случайным образом при использовании с Graphviz! - PullRequest
4 голосов
/ 12 февраля 2010

Я использую точку graphviz для создания некоторых графиков SVG для веб-приложения. Я называю точку, используя Popen:

    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)

Что происходит, так это то, что точечная программа генерирует ошибки вроде:

    Error: not well-formed (invalid token) in line 1 
 ... <tr><td cellpadding="4bgcolor="#EEE8AA"> ...
in label of node n260

Эта очевидная ошибка, скорее всего, НЕ во входной строке. В частности, если я сохраню его в str.txt с кодировкой utf-8 и сделаю

/usr/bin/dot -Kfdp -Tsvg < str.txt > myimg.svg

Я получаю желаемый результат. Единственное «особенное» в str - это то, что он содержит символы, такие как датский øæå.

Сейчас я понятия не имею, что мне делать. Проблема вполне может быть в точке; но, безусловно, это вызвано тем, что Popen отличается от использования <из оболочки, и я понятия не имею, с чего начать. Буду очень признателен за любую помощь или идеи для альтернативного вызова точки (помимо записи всех данных в файл и вызова этого!)! </p>

1 Ответ

3 голосов
/ 12 февраля 2010

Похоже, что вы должны делать:

stdout, stderr = p.communicate(str.encode('utf-8'))

(за исключением, конечно, того, что вы не должны скрывать встроенную str.) Тип Unicode в Python содержит данные Unicode, not UTF-8. Если вы хотите UTF-8, вам нужно явно закодировать его.

Кроме того, нет смысла использовать shell=True в этом фрагменте, и при этом литерал Юникода не передается в подпроцесс. Откройте особенно хорошую идею (в любом случае он просто кодируется в ASCII). не нужен - Python знает, что строка продолжается, потому что у вас есть открытая скобка, которая еще не была закрыта. Итак, используйте:

p = subprocess.Popen(['/usr/bin/dot', '-Kfdp', '-Tsvg'],
    stdin=subprocess.PIPE, stdout=subprocess.PIPE)
...