it-swarm.com.de

StringIO in Python3

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

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

Ich erhalte folgenden Fehler:

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

und wenn ich import StringIO schreibe, heißt es

ImportError: No module named 'StringIO'
368
user1591744

wenn ich Import StringIO schreibe, heißt es, dass es kein solches Modul gibt.

Von Was ist neu in Python 3. :

Die Module StringIO und cStringIO sind nicht mehr vorhanden. Importieren Sie stattdessen das Modul io und verwenden Sie io.StringIO oder io.BytesIO für Text bzw. Daten.

.


Eine möglicherweise nützliche Methode zum Korrigieren von Python 2-Code, um auch in Python 3 zu funktionieren (Vorbehalt-Emptor):

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

Hinweis: Dieses Beispiel ist möglicherweise tangential zum Hauptthema der Frage und wird nur berücksichtigt, wenn das fehlende StringIO -Modul allgemein adressiert wird. Für eine direktere Lösung die Nachricht TypeError: Can't convert 'bytes' object to str implicitly, siehe diese Antwort .

611
nobar

In meinem Fall habe ich verwendet:

from io import StringIO
112
Kamesh Jungi

Ein Python 3 numpy.genfromtxt erwartet einen Bytestream. Verwenden Sie Folgendes:

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

Vielen Dank, dass Sie OP für Ihre Frage und Roman für Ihre Antwort. Ich musste ein bisschen suchen, um das 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:

dtype = "| Sx", wobei x für {1, 2, 3, ...} steht:

dtypes. Unterschied zwischen S1 und S2 in Python

Die Zeichenfolgen | S1 und | S2 sind Datentypdeskriptoren. Das erste bedeutet, dass das Array Zeichenfolgen der Länge 1 und das zweite Zeichenfolgen der Länge 2 enthält.

23
Victoria Stuart

Sie können das StringIO aus dem sechs Modul verwenden:

import six
import numpy

x = "1 3\n 4.5 8"
numpy.genfromtxt(six.StringIO(x))
17
Tiago Coutinho

Roman Shapovalovs Code sollte sowohl in Python 3.x als auch in Python 2.6/2.7 funktionieren. Hier ist es wieder 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. ]])
_

Erklärung für Python 3.x:

  • _numpy.genfromtxt_ nimmt einen Bytestream (ein dateiähnliches Objekt, das anstelle von Unicode als Byte interpretiert wird).
  • _io.BytesIO_ nimmt eine Byte-Zeichenfolge und gibt einen Byte-Stream zurück. _io.StringIO_ hingegen würde eine Unicode-Zeichenfolge verwenden und einen Unicode-Stream zurückgeben.
  • x wird ein Zeichenfolgenliteral zugewiesen, das in Python 3.x eine Unicode-Zeichenfolge ist.
  • encode() nimmt die Unicode-Zeichenfolge x und erstellt daraus eine Byte-Zeichenfolge, wodurch _io.BytesIO_ ein gültiges Argument erhält.

Der einzige Unterschied für Python 2.6/2.7 besteht darin, dass x eine Byte-Zeichenfolge ist (vorausgesetzt, _from __future__ import unicode_literals_ wird nicht verwendet), und dann nimmt encode() die Byte-Zeichenfolge x und macht immer noch dasselbe Byte-String raus. Das Ergebnis ist also dasselbe.


Da dies eine der beliebtesten Fragen von SO zu StringIO ist, finden Sie hier 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 eine Byte-Zeichenfolge. Gibt einen Bytestream zurück.
  • io.StringIO (Python 2.6, 2.7 und 3.x) - Verwendet eine Unicode-Zeichenfolge. Gibt einen Unicode-Stream zurück.
  • StringIO.StringIO (Python 2.x) - Nimmt eine Byte- oder Unicode-Zeichenfolge an. Wenn Byte-Zeichenfolge, wird ein Byte-Stream zurückgegeben. Wenn es sich um eine Unicode-Zeichenfolge handelt, wird ein Unicode-Stream zurückgegeben.
  • cStringIO.StringIO (Python 2.x) - Schnellere Version von _StringIO.StringIO_, kann jedoch keine Unicode-Zeichenfolgen akzeptieren, die Nicht-ASCII-Zeichen enthalten.

Beachten Sie, dass _StringIO.StringIO_ als _from StringIO import StringIO_ importiert und dann als StringIO(...) verwendet wird. Entweder das, oder du machst _import StringIO_ und benutzt dann StringIO.StringIO(...). Der Modulname und der Klassenname sind einfach gleich. Auf diese Weise ähnelt es datetime.

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

  • Wenn Sie nur Python 3.x unterstützen: Verwenden Sie je nach Art einfach _io.BytesIO_ oder _io.StringIO_ von Daten, mit denen 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: Am einfachsten ist es immer noch, _io.BytesIO_ oder _io.StringIO_ zu verwenden. Obwohl _StringIO.StringIO_ flexibel ist und daher für 2.6/2.7 bevorzugt erscheint, kann diese Flexibilität Fehler maskieren, die in 3.x auftreten. Zum Beispiel hatte ich einen Code, der _StringIO.StringIO_ oder _io.StringIO_ verwendete, je nach Version von Python, aber ich habe tatsächlich eine Byte-Zeichenfolge übergeben.Python 3.x ist fehlgeschlagen und musste behoben werden.

    Ein weiterer Vorteil von _io.StringIO_ ist die Unterstützung für universelle Zeilenumbrüche. Wenn Sie das Schlüsselwortargument _newline=''_ an _io.StringIO_ übergeben, kann es Zeilen in _\n_, _\r\n_ oder _\r_ teilen. Ich fand heraus, dass _StringIO.StringIO_ insbesondere bei _\r_ auslösen würde.

    Beachten Sie, dass wenn Sie BytesIO oder StringIO von six importieren, Sie _StringIO.StringIO_ in Python 2.x und die entsprechende Klasse von io in Python erhalten. 3.x. Wenn Sie der Einschätzung meiner vorherigen Absätze zustimmen, sollten Sie in diesem Fall six vermeiden und stattdessen nur von io importieren.

  • Wenn Sie Python 2.5 oder niedriger und 3.x unterstützen: Sie benötigen _StringIO.StringIO_ für 2.5 oder niedriger, Sie können also auch six verwenden. Beachten Sie jedoch, 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 überhaupt möglich ist.

15
S. Kirby

Damit Beispiele aus hier mit Python 3.5.2 funktionieren, können Sie wie folgt umschreiben:

import io
data =io.BytesIO(b"1, 2, 3\n4, 5, 6") 
import numpy
numpy.genfromtxt(data, delimiter=",")

Der Grund für die Änderung kann sein, dass sich der Inhalt einer Datei in Daten (Bytes) befindet, die erst dann Text enthalten, wenn sie irgendwie dekodiert wurden. genfrombytes ist möglicherweise ein besserer Name als genfromtxt.

6