639 Stimmen

Wie benutzt man StringIO in Python3?

Ich verwende Python 3.2.1 und ich kann nicht importieren die StringIO Modul. Ich verwende io.StringIO und es funktioniert, aber ich kann es nicht verwenden mit numpy 's genfromtxt wie diese:

x="1 3\n 4.5 8"        
numpy.genfromtxt(io.StringIO(x))

Ich erhalte den folgenden Fehler:

TypeError: Can't convert 'bytes' object to str implicitly  

und wenn ich schreibe import StringIO heißt es

ImportError: No module named 'StringIO'

1064voto

Brent Bradburn Punkte 45995

Wenn ich import StringIO schreibe, heißt es, dass es kein solches Modul gibt.

Von Was ist neu in Python 3.0 :

Le StringIO y cStringIO Module sind verschwunden. Importieren Sie stattdessen die io Modul und verwenden io.StringIO o io.BytesIO für Text und Daten bzw. Daten.

.


Eine möglicherweise nützliche Methode, um Python-2-Code so zu verändern, dass er auch in Python 3 funktioniert (caveat emptor):

try:
    from StringIO import StringIO ## for Python 2
except ImportError:
    from io import StringIO ## for Python 3

Hinweis: Dieses Beispiel hat möglicherweise nichts mit dem Hauptthema der Frage zu tun und soll nur als Anhaltspunkt dienen, wenn es darum geht, die fehlenden Angaben allgemein zu machen. StringIO Modul. Für eine direktere Lösung wird die Nachricht TypeError: Can't convert 'bytes' object to str implicitly siehe diese Antwort .

172voto

Kamesh Jungi Punkte 5864

In meinem Fall habe ich verwendet:

from io import StringIO

79voto

Roman Shapovalov Punkte 2785

Zu Python 3 numpy.genfromtxt erwartet einen Bytestrom. Verwenden Sie das Folgende:

numpy.genfromtxt(io.BytesIO(x.encode()))

27voto

S. Kirby Punkte 6945

Der Code von Roman Shapovalov sollte sowohl in Python 3.x als auch in Python 2.6/2.7 funktionieren. Hier ist er noch einmal mit dem vollständigen Beispiel:

import io
import numpy
x = "1 3\n 4.5 8"
numpy.genfromtxt(io.BytesIO(x.encode()))

Ausgabe:

array([[ 1. ,  3. ],
       [ 4.5,  8. ]])

Erläuterung für Python 3.x:

  • numpy.genfromtxt nimmt einen Byte-Stream (ein dateiähnliches Objekt, das als Bytes anstelle von Unicode interpretiert wird).
  • io.BytesIO nimmt einen Byte-String und gibt einen Byte-Stream zurück. io.StringIO hingegen würde eine Unicode-Zeichenkette nehmen und einen Unicode-Stream zurückgeben.
  • x wird ein String-Literal zugewiesen, das in Python 3.x ein Unicode-String ist.
  • encode() nimmt die Unicode-Zeichenkette x und macht daraus eine Byte-Zeichenkette, was zu io.BytesIO ein stichhaltiges Argument.

Der einzige Unterschied für Python 2.6/2.7 ist, dass x eine Byte-Zeichenkette ist (unter der Annahme, dass from __future__ import unicode_literals nicht verwendet wird), und dann encode() nimmt die Byte-Zeichenkette x und macht daraus immer noch die gleiche Byte-Zeichenkette. Das Ergebnis ist also dasselbe.


Da dies eine der am häufigsten gestellten Fragen von SO ist, die StringIO Hier finden Sie weitere Erklärungen zu den Import-Anweisungen und den verschiedenen Python-Versionen.

Hier sind die Klassen, die einen String nehmen und einen Stream zurückgeben:

  • io.BytesIO (Python 2.6, 2.7 und 3.x) - Nimmt einen Byte-String entgegen. Gibt einen Byte-Stream zurück.
  • io.StringIO (Python 2.6, 2.7 und 3.x) - Nimmt eine Unicode-Zeichenkette entgegen. Gibt einen Unicode-Stream zurück.
  • StringIO.StringIO (Python 2.x) - Nimmt einen Byte-String oder einen Unicode-String an. Falls Byte-String, wird ein Byte-Stream zurückgegeben. Falls Unicode-String, wird ein Unicode-Stream zurückgegeben.
  • cStringIO.StringIO (Python 2.x) - Schnellere Version von StringIO.StringIO , kann aber keine Unicode-Zeichenfolgen annehmen, die Nicht-ASCII-Zeichen enthalten.

Beachten Sie, dass StringIO.StringIO wird importiert als from StringIO import StringIO dann verwendet als StringIO(...) . Entweder das, oder Sie tun import StringIO und verwenden Sie dann StringIO.StringIO(...) . Der Modulname und der Klassenname sind zufällig identisch. Es ist ähnlich wie bei datetime auf diese Weise.

Was zu verwenden ist, hängt von den von Ihnen unterstützten Python-Versionen ab:

  • Wenn Sie nur Python 3.x unterstützen: Verwenden Sie einfach io.BytesIO o io.StringIO je nachdem, mit welcher Art von Daten Sie arbeiten.

  • Wenn Sie sowohl Python 2.6/2.7 als auch 3.x unterstützen, oder versuchen, Ihren Code von 2.6/2.7 auf 3.x umzustellen: Die einfachste Möglichkeit ist immer noch die Verwendung von io.BytesIO o io.StringIO . Obwohl StringIO.StringIO flexibel ist und daher für 2.6/2.7 vorzuziehen scheint, könnte diese Flexibilität Fehler verbergen, die sich in 3.x manifestieren werden. Ich hatte zum Beispiel einen Code, der StringIO.StringIO o io.StringIO je nach Python-Version, aber ich war eigentlich Übergabe einer Byte-Zeichenfolge, so dass, wenn ich um zu testen, es in Python 3.x es fehlgeschlagen und musste behoben werden.

    Ein weiterer Vorteil der Verwendung von io.StringIO ist die Unterstützung für universelle Zeilenumbrüche. Wenn Sie das Schlüsselwortargument newline='' en io.StringIO kann das Programm die Zeilen auf jeder beliebigen \n , \r\n , oder \r . Ich fand, dass StringIO.StringIO würde stolpern über \r im Besonderen.

    Beachten Sie, dass Sie beim Import von BytesIO o StringIO von six erhalten Sie StringIO.StringIO in Python 2.x und die entsprechende Klasse aus io in Python 3.x. Wenn Sie mit der Einschätzung in den vorangegangenen Abschnitten übereinstimmen, ist dies tatsächlich ein Fall, in dem Sie vermeiden sollten six und importieren Sie einfach von io stattdessen.

  • Wenn Sie Python 2.5 oder niedriger und 3.x unterstützen: Sie benötigen StringIO.StringIO für 2,5 oder niedriger, also können Sie auch six . Sie sollten sich jedoch darüber im Klaren sein, dass es im Allgemeinen sehr schwierig ist, sowohl 2.5 als auch 3.x zu unterstützen. Sie sollten daher in Erwägung ziehen, Ihre niedrigste unterstützte Version auf 2.6 zu erhöhen, wenn dies möglich ist.

26voto

Victoria Stuart Punkte 3912

Vielen Dank, Herr OP, für Ihre Frage und an Roman für Ihre Antwort. Ich musste ein bisschen suchen, um dies zu finden; ich hoffe, das Folgende hilft anderen.

Python 2.7

Siehe: https://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html

import numpy as np
from StringIO import StringIO

data = "1, abc , 2\n 3, xxx, 4"

print type(data)
"""
<type 'str'>
"""

print '\n', np.genfromtxt(StringIO(data), delimiter=",", dtype="|S3", autostrip=True)
"""
[['1' 'abc' '2']
 ['3' 'xxx' '4']]
"""

print '\n', type(data)
"""
<type 'str'>
"""

print '\n', np.genfromtxt(StringIO(data), delimiter=",", autostrip=True)
"""
[[  1.  nan   2.]
 [  3.  nan   4.]]
"""

Python 3.5:

import numpy as np
from io import StringIO
import io

data = "1, abc , 2\n 3, xxx, 4"
#print(data)
"""
1, abc , 2
 3, xxx, 4
"""

#print(type(data))
"""
<class 'str'>
"""

#np.genfromtxt(StringIO(data), delimiter=",", autostrip=True)
# TypeError: Can't convert 'bytes' object to str implicitly

print('\n')
print(np.genfromtxt(io.BytesIO(data.encode()), delimiter=",", dtype="|S3", autostrip=True))
"""
[[b'1' b'abc' b'2']
 [b'3' b'xxx' b'4']]
"""

print('\n')
print(np.genfromtxt(io.BytesIO(data.encode()), delimiter=",", autostrip=True))
"""
[[  1.  nan   2.]
 [  3.  nan   4.]]
"""

Nebenbei bemerkt:

dtype="|Sx", wobei x = einer der Werte { 1, 2, 3, ...}:

dtypes. Unterschied zwischen S1 und S2 in Python

"Die Zeichenfolgen |S1 und |S2 sind Datentyp-Deskriptoren; die erste bedeutet, dass das Array Zeichenfolgen der Länge 1 enthält, die zweite der Länge 2. ..."

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X