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'
wenn ich Import StringIO schreibe, heißt es, dass es kein solches Modul gibt.
Von Was ist neu in Python 3. :
Die Module
StringIO
undcStringIO
sind nicht mehr vorhanden. Importieren Sie stattdessen das Modulio
und verwenden Sieio.StringIO
oderio.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 NachrichtTypeError: Can't convert 'bytes' object to str implicitly
, siehe diese Antwort .
In meinem Fall habe ich verwendet:
from io import StringIO
Ein Python 3 numpy.genfromtxt
erwartet einen Bytestream. Verwenden Sie Folgendes:
numpy.genfromtxt(io.BytesIO(x.encode()))
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.
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.
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
.