2010-02-12 13 views
4

J'utilise le point de graphviz pour générer des graphiques svg pour une application web. J'appeler en utilisant les points sur Popen:subprocess.Popen (..). Communiquer (..) jeter des données au hasard lorsqu'il est utilisé avec graphviz!

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) 

Quelle happends est que les erreurs de jet de programme de points comme:

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

Cette erreur évidente est certainement pas dans la chaîne d'entrée. En particulier, si je l'enregistre à str.txt avec encodage UTF-8 et ne

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

Je reçois la sortie désirée. La seule chose "spéciale" à propos de str est qu'il contient des caractères comme le øæå danois.

En ce moment je n'ai aucune idée de ce que je devrais faire. Le problème peut très bien être en point; mais il semble certainement être déclenché par Popen étant différent de l'utilisation < du shell, et je n'ai aucune idée par où commencer. Toute aide ou idée pour l'appel de points (en plus d'écrire toutes les données dans un fichier et d'appeler ça!) Serait très appréciée!

Répondre

3

On dirait que vous devriez faire:

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

(sauf, bien sûr, que vous ne devriez pas l'ombre de la str builtin.) Le type unicode en Python contient des données unicode, pas UTF-8 . Si vous voulez UTF-8, vous devez l'encoder explicitement. En plus de cela, il n'y a aucune raison d'utiliser shell=True dans cet extrait, ni le littéral Unicode transmis au sous-processus. Ouvrez une idée particulièrement bonne (elle est tout simplement encodée en ASCII.) Et l'antislash à la fin est inutile - Python sait que la ligne est continuée, car vous avez une parenthèse ouverte qui n'a pas encore été fermée. Donc, utilisez:

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

Merci Thomas! Cela a fait l'affaire. Boy je me sens stupide, je passe 5 heures 'débogage' un problème unicode trivial :-(. Aussi merci pour les conseils de style Désolé, si mon code merdique causé des dommages physiques! ;-) –

+0

Je reçois "UnicodeEncodeError: ' codec ascii 'ne peut pas encoder les caractères en position 29-31: ordinal pas dans la plage (128) ". Une idée? tia btw, c'est 2.6 sur Windows: – nad2000