Python3'te StringIO


474

Python 3.2.1 kullanıyorum ve StringIOmodülü alamıyorum . Kullandığım io.StringIOve çalıştığını, ancak bunu kullanamazsınız numpys' genfromtxtböyle:

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

Aşağıdaki hatayı alıyorum:

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

ve yazdığımda import StringIOşöyle diyor

ImportError: No module named 'StringIO'

Yanıtlar:


774

i ithalat StringIO yazarken böyle bir modül yok diyor.

Gönderen Yenilikler In Python 3.0 :

StringIOVe cStringIOmodüller gittiler. Bunun yerine, io modülü içe aktarın ve sırasıyla metin ve veriler için io.StringIOveya kullanın io.BytesIO.

.


Python 3'te de çalışacak bazı Python 2 kodlarını düzeltmek için muhtemelen yararlı bir yöntem (uyarı emptor):

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

Not: Bu örnek, sorunun ana sorununa teğet olabilir ve yalnızca eksik StringIOmodülü genel olarak ele alırken dikkate alınması gereken bir şey olarak dahil edilir . Daha doğrudan bir çözüm mesajı TypeError: Can't convert 'bytes' object to str implicitlyiçin bu cevaba bakınız .


13
Bunlardan bahsetmeye değmez, bu yüzden tek TypeErrorbaşına bu değişikliği yaparsanız s (dize argümanı bekleniyor, 'bayt' var) ile sonuçlanabilir . Python 3'te btyes ve str (unicode) dikkatlice ayırt etmeniz gerekir
Andy Hayden

7
Benim gibi yeni başlayanlar için: from io import StringIO, bunu io.StringIO () değil, StringIO () olarak adlandırdığınız anlamına gelir.
Noumenon

11
Aslında Python 2 ve 3 ile nasıl uyumlu from io import StringIO
olunur

8
Python 3'teki numpy.genfromtxt () için BU SADECE YANLIŞ. Lütfen Roman Shapovalov'un cevabına bakın.
Bill Huang

2
@nobar: İkincisi. Orijinal soru, modülün StringIOgittiği ve from io import BytesIObunun yerine uygulanması gereken python 3.x kullanır . Kendimi python 3.5 @ eclipse pyDev + win7 x64 üzerinde test ettim. Lütfen yanılmışsam bana bildirin teşekkürler.
Bill Huang


70

Python 3'te numpy.genfromtxtbir bayt akışı beklenir. Aşağıdakileri kullanın:

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

24

Sorunuz için OP ve cevabınız için Roman teşekkür ederiz. Bunu bulmak için biraz araştırmak zorunda kaldım; Umarım aşağıdakiler başkalarına yardımcı olur.

Python 2.7

Bkz. 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.]]
"""

kenara:

dtype = "| Sx"; burada x = {1, 2, 3, ...} 'den herhangi biri:

dtypes. Python'da S1 ve S2 arasındaki fark

"| S1 ve | S2 dizeleri veri türü tanımlayıcılarıdır; birincisi, dizinin 1 uzunluğunda, ikinci 2 uzunluğunda dizeleri tuttuğu anlamına gelir."



17

Roman Shapovalov'un kodu Python 3.x ve Python 2.6 / 2.7'de çalışmalıdır. İşte yine tam örnekle:

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

Çıktı:

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

Python 3.x için açıklama:

  • numpy.genfromtxt bayt akışını (Unicode yerine bayt olarak yorumlanan dosya benzeri bir nesne) alır.
  • io.BytesIO bir bayt dizesi alır ve bir bayt akışı döndürür. io.StringIOÖte yandan, bir Unicode dizesi alıp bir Unicode akışı döndürür.
  • x Python 3.x içinde bir Unicode dize olan bir dize değişmez değeri atanır.
  • encode()Unicode dizesini alır xve bir bayt dizesi oluşturur, böylece io.BytesIOgeçerli bir argüman verir.

Python 2.6 / 2.7 için tek fark x, bir bayt dizesidir ( from __future__ import unicode_literalskullanılmadığı varsayılır ) ve daha sonra encode()bayt dizesini alır xve yine de aynı bayt dizesini çıkarır. Sonuç aynı.


Bu, SO'nun en popüler sorularından biri olduğu StringIOiçin, ithalat ifadeleri ve farklı Python sürümleri hakkında daha fazla açıklama.

Bir dize alıp bir akış döndüren sınıflar şunlardır:

  • io.BytesIO(Python 2.6, 2.7 ve 3.x) - Bayt dizesi alır. Bayt akışı döndürür.
  • io.StringIO(Python 2.6, 2.7 ve 3.x) - Bir Unicode dizesi alır. Bir Unicode akışı döndürür.
  • StringIO.StringIO(Python 2.x) - Bir bayt dizesi veya Unicode dizesi alır. Bayt dizesi varsa, bir bayt akışı döndürür. Unicode dizesi bir Unicode akışı döndürür.
  • cStringIO.StringIO(Python 2.x) - StringIO.StringIOASCII olmayan karakterler içeren Unicode dizelerinin daha hızlı sürümü , ancak alınamıyor.

Not StringIO.StringIOolarak alınır from StringIO import StringIO, sonra olarak kullanılır StringIO(...). Ya bu, ya sen import StringIOkullan ve sonra kullan StringIO.StringIO(...). Modül adı ve sınıf adı aynıdır. Bu datetimeşekilde.

Desteklenen Python sürümlerinize bağlı olarak ne kullanılır?

  • Yalnızca Python 3.x'i destekliyorsanız: Sadece io.BytesIOveya io.StringIOne tür verilerle çalıştığınıza bağlı olarak kullanın .

  • Hem Python 2.6 / 2.7 hem de 3.x'i destekliyorsanız ya da kodunuzu 2.6 / 2.7'den 3.x'e geçirmeye çalışıyorsanız: En kolay seçenek hala io.BytesIOya da kullanmaktır io.StringIO. StringIO.StringIOEsnek olmasına rağmen 2.6 / 2.7 için tercih edilmiş gibi görünse de, bu esneklik 3.x'te ortaya çıkacak hataları maskeleyebilir. Örneğin, kullanılan StringIO.StringIOveya io.StringIOPython sürümüne bağlı olarak bazı kod vardı , ama aslında bir bayt dizesi geçiyordu, bu yüzden Python 3.x test etmek için etrafında var başarısız oldu ve düzeltilmesi gerekiyordu.

    Kullanmanın bir diğer avantajı, io.StringIOevrensel satırsonu desteğidir. Anahtar kelime argüman iletirseniz newline=''içine io.StringIO, o herhangi çizgiler bölmek mümkün olacak \n, \r\nya da \r. Ben bu StringIO.StringIOkadar gezecek buldum\r özellikle .

    İçeri BytesIOveya StringIOdışarı aktarırsanız six, StringIO.StringIOPython 2.x'e ve uygun sınıfı ioPython 3.x'ten alacağınıza dikkat edin . Önceki paragraflarımın değerlendirmesini kabul ediyorsanız, bu aslında kaçınmanız sixve iobunun yerine içe aktarmanız gereken bir durumdur .

  • Python 2.5 veya daha düşük bir sürümü ve 3.x'i destekliyorsanız: 2.5 veya daha düşük bir sürüme ihtiyacınız StringIO.StringIOolacaktır, bu nedenle de kullanabilirsiniz six. Ancak, hem 2.5 hem de 3.x'i desteklemenin genellikle çok zor olduğunu unutmayın, bu nedenle mümkünse desteklenen en düşük sürümünüzü 2.6'ya çarpmayı düşünmelisiniz.


7

Buradan örneklerin Python 3.5.2 ile çalışmasını sağlamak için aşağıdaki gibi yeniden yazabilirsiniz:

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

Değişikliğin nedeni, bir dosyanın içeriğinin, bir şekilde kodu çözülene kadar metin oluşturmayan verilerde (bayt) olması olabilir. genfrombytesdaha iyi bir isim olabilir genfromtxt.


-4

bunu dene

StringIO'dan içe aktarma StringIO

x = "1 3 \ n 4.5 8"

numpy.genfromtxt (StringIO (x))

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.