2017-12-22 17 views
0

Ich habe eine Flask-Anwendung (Linux, Apache mit mod_wsgi, Python 3), die ein Shell-Skript mit einigen Argumenten aufruft. Wenn es irgendwelche Nicht-ASCII-Zeichen in den subprocess.run() Befehlsargumente sind, Fehler folgende tritt in der Anwendung:subprocess.run() Argument Codierung

'ascii' codec can't encode characters in position 5-6: ordinal not in range(128)

ich viel Zeit damit verbracht, es zu beheben.

Kein solches Problem existiert in der Befehlszeile, nur in der Anwendung.

Die gesamte Anwendung Ausgabe ist in Unicode und es gibt keine Probleme damit. Nach einigen Recherchen kam ich zu dem Schluss, dass das Problem mit der "Dateisystem-Codierung" zu tun hat.

Ich habe einige Protokollanweisungen zu meinem run.wsgi Skript hinzugefügt. Die FS-Codierung war tatsächlich 'ascii' (und 'utf-8' in der Befehlszeile).

Im nächsten Schritt fand ich diesen Artikel How to change file system encoding via python?

Der Server Apache wurde mit LANG=C in seiner Umgebung gestartet. Ich habe es zu C.UTF-8 trotz Warnungen in /etc/sysconfig/httpd geändert. Das half nicht, die FS-Codierung war immer noch 'ascii'. Ich habe dann sogar die sys.getfilesystemencoding() zu lambda: 'utf-8' monkey-gepatcht. Aber der Fehler ist immer noch da.

Ich habe den httpd-Dienst nach jeder Änderung ordnungsgemäß neu gestartet.

Ich bin am Ende meines Wissens.

  1. Ist mein Problem wirklich durch die FS-Codierung verursacht?
  2. Wenn ja, warum sind meine Versuche, es in utf-8 zu ändern, fehlgeschlagen?
  3. Am wichtigsten: Wie kann ich dieses Problem lösen?

UPDATE1:

Code-Schnipsel:

import subprocess as sub 
    cmdresult = sub.run(
     [SCRIPT, tid, days, name], 
     stdin=sub.DEVNULL, stdout=sub.PIPE, stderr=sub.DEVNULL, 
     encoding='ascii', # 'utf-8' will not help, this affects stdin, stdout I/O only 
     check=True) 
+1

Rufen Sie mit 'shell = True' auf oder nicht? Übergeben Sie Argumente wie eine Zeichenfolge oder eine Liste? Bitte zeigen Sie den tatsächlichen Code, der das 'subprocess' Modul verwendet. –

+0

Auf OS-Ebene ist es 'exec()' und Freunden egal, welche Kodierung Sie für die Argumente verwenden, die Sie an einen Unterprozess übergeben: POSIX erfordert nur, dass sie als C 'char *' - Zeichenfolge dargestellt werden können zum Subprozess, um sie zu dekodieren. –

+0

@DanielPryden Code angehängt, 'shell = False' standardmäßig. – VPfB

Antwort

0

Im Rahmen der mod_wsgi, sollten Sie sicherstellen, dass Sie mod_wsgi Daemon-Modus und stellen Sie die lang/locale für die mod_wsgi Daemon Prozessgruppe verwenden. Für eine viel detailliertere Erklärung, die hier zu wiederholen, zu viel ist, finden Sie unter:

+0

Ich habe vor ein paar Tagen Ihren Blog über den Deamon-Modus gelesen und die Änderung vom Embedded- in den Daemon-Modus hoch auf meine Liste gesetzt. Danke für das Schreiben dieser Blogs. In Bezug auf dieses Problem denke ich, dass es sehr wenig mit "mod_wsgi" verbunden ist. Ich habe eine Python-Lösung gefunden. – VPfB

0

(eigene Frage zu beantworten gehofft, dass es für andere hilfreich sein könnten)

ich einen kurzen Test gemacht Programm. Dies ist, was ich gefunden habe:

  1. Dateisystem-Codierung ist der Schlüsselpunkt.
  2. Monkey Patching funktioniert nicht. Nun, das ist OK. Es ist sowieso nicht akzeptabel als Lösung.
  3. LANG=C.UTF-8 erfordert das Gebietsschema installiert und es war nicht auf meinem System (mit locale -a überprüft). Aber auf einem zweiten System, wo es verfügbar war, funktionierte es.
  4. ich die Codierung explizit und übergeben Bytes als eine der args machen kann:

    cmdresult = sub.run(
        [SCRIPT, tid, days, name.encode('utf-8')], 
        ... 
    

Dies funktioniert, aber eine Frage remianed:

Ist es mit der Dokumentation erfüllen?

Alles, was ich finden konnte, ist:

args should be a sequence of program arguments or else a single string

Und ich habe es als eine Zeichenfolge oder eine Liste von Zeichenketten verstehen, aber eigentlich ist es nicht eine Liste, welche Arten angeben. Ich ging auch und int vorbei, um zu sehen, was passieren wird. Ich habe diesen Fehler:

expected str, bytes or os.PathLike object

Also meine Lösung scheint in Ordnung zu sein.

Verwandte Themen