StringIO示例不起作用

13 浏览
0 Comments

StringIO示例不起作用

我尝试理解numpy.getfromtxt方法和io.StringIO的工作原理。

在官方网站上(https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.genfromtxt.html#numpy.genfromtxt)上找到了一些示例。这是其中之一:

s = StringIO("1,1.3,abcde")
data = np.genfromtxt(s, dtype=[('myint','i8'),('myfloat','f8'),('mystring','S5')], delimiter=",")

但是当我在我的电脑上运行这段代码时,我得到了TypeError: must be str or None, not bytes的错误。

请告诉我如何解决这个问题?

0
0 Comments

从上述内容中可以得出以下结论:

问题的原因是在旧版本的numpy中,使用StringIO对象作为输入时会出错。根据文档,Python 3k中的生成器必须返回字节字符串。解决方法是使用BytesIO对象作为输入。

具体的解决方法如下:

import io
s = io.BytesIO(b"1,1.3,abcde")

文章整理如下:

考虑升级numpy,因为对于当前版本的numpy,您的代码可以按照原样运行。请参阅1.14.0版本的发布说明中的提及和“np.genfromtxt”中的“Encoding argument for text IO functions”部分,了解有关numpy中相关更改的详细信息。

对于旧版本的numpy,您在输入中使用了字符串对象,但您链接的文档中指出:

请注意,在Python 3k中,生成器必须返回字节字符串。

所以按照文档的指示,给它一个字节字符串:

import io
s = io.BytesIO(b"1,1.3,abcde")

我有点惊讶StringIO起作用了,这就是我包含版本号的原因。我有个模糊的记忆,以前我必须使用BytesIO。

这一切都有点令人困惑,因为genfromtxt这个名字是不准确的,以及dtype中的符号'S5'与'U5'的使用。

尽管使用'U5'和'S5'与输入字符串的性质无关。如果给定一个文件名,genfromtxt将以'rb'模式打开文件,并尽可能使用字节字符串进行操作(为了与Python 2的行为一致)。

最近我看到了VisibleDeprecationWarning警告,但我忽略了它。这是一个受欢迎的升级。

0
0 Comments

问题的出现原因是在较旧版本的NumPy中,当使用dtype=None时,genfromtxt会创建S字符串,而不是默认的Unicode字符串。因此,在较旧的版本中,无法正确地读取字符串。解决方法是升级到NumPy的1.14版本或更高版本,这样就可以通过设置encoding=None来控制默认的字符串编码类型,从而正确地读取和处理字符串。

以下是解决方法的示例代码:

In [219]: s = io.StringIO("1,1.3,abcde")
In [220]: np.genfromtxt(s, dtype=None, delimiter=",")
/usr/local/bin/ipython3:1: VisibleDeprecationWarning: Reading unicode strings without specifying the encoding argument is deprecated. Set the encoding, use None for the system default.
  #!/usr/bin/python3
Out[220]: 
array((1, 1.3, b'abcde'),
      dtype=[('f0', '<i4'), ('f1', '<f8'), ('f2', 'S5')])
In [221]: s = io.StringIO("1,1.3,abcde")
In [222]: np.genfromtxt(s, dtype=None, delimiter=",",encoding=None)
Out[222]: 
array((1, 1.3, 'abcde'),
      dtype=[('f0', '<i4'), ('f1', '<f8'), ('f2', '<U5')])
In [223]: s = """1,1.3,abcde
4,1.3,two""".splitlines()
In [224]: np.genfromtxt(s, dtype=None, delimiter=",",encoding=None)
Out[224]: 
array([(1, 1.3, 'abcde'), (4, 1.3, 'two')],
      dtype=[('f0', '<i4'), ('f1', '<f8'), ('f2', '<U5')])

这是一个较新的更改。OP显然使用的是较旧的NumPy版本。通过升级到较新的版本,我们可以正确地读取和处理字符串。

0