2013-05-04 64 views
1

使用namedtuple文档例子作为我在Python 3.3的模板,我有以下的代码来下载一个CSV,把它变成了一系列namedtuple子类的实例:有没有更好的方法来使用urlopen做csv/namedtuple?

from collections import namedtuple 
from csv import reader 
from urllib.request import urlopen  

SecurityType = namedtuple('SecurityType', 'sector, name') 

url = 'http://bsym.bloomberg.com/sym/pages/security_type.csv' 
for sec in map(SecurityType._make, reader(urlopen(url))): 
    print(sec) 

这引发了以下异常:

Traceback (most recent call last): 
    File "scrap.py", line 9, in <module> 
    for sec in map(SecurityType._make, reader(urlopen(url))): 
_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?) 

我知道问题是urlopen返回的是字节而不是字符串,而且我需要在某个时刻解码输出。以下是我正在做的,现在,使用StringIO的:

from collections import namedtuple 
from csv import reader 
from urllib.request import urlopen 
import io 

SecurityType = namedtuple('SecurityType', 'sector, name') 

url = 'http://bsym.bloomberg.com/sym/pages/security_type.csv' 
reader_input = io.StringIO(urlopen(url).read().decode('utf-8')) 

for sec in map(SecurityType._make, reader(reader_input)): 
    print(sec) 

这闻起来很有趣,因为我基本上遍历字节的缓冲区,解码,停顿,然后遍历新的字符串缓冲区。没有两次迭代,是否有更多的Pythonic方法来做到这一点?

+0

嗯。我要推荐的东西(使用'TextIOWrapper')不起作用,它应该有IMO。一些挖掘显示[这个错误(问题16723)](http://bugs.python.org/issue16723),这似乎是问题。 – DSM 2013-05-04 13:54:14

+1

@DSM:该补丁已在2月份应用,因此最新的3.x版本包含它。您使用的是什么版本的3.x? – 2013-05-04 13:59:06

+0

3.3.0。我喜欢保持最新状态,但自从3.3.1发布以来还没有一个月。 :^) – DSM 2013-05-04 14:01:37

回答

5

使用io.TextIOWrapper()解码urllib响应:

reader_input = io.TextIOWrapper(urlopen(url), encoding='utf8', newline='') 

现在csv.reader传递的完全相同的接口在文本模式在文件系统中打开一个普通的文件时,它会得到。

有了这个改变你的例子网址为我工作有关Python 3.3.1:

>>> for sec in map(SecurityType._make, reader(reader_input)): 
...  print(sec) 
... 
SecurityType(sector='Market Sector', name='Security Type') 
SecurityType(sector='Comdty', name='Calendar Spread Option') 
SecurityType(sector='Comdty', name='Financial commodity future.') 
SecurityType(sector='Comdty', name='Financial commodity generic.') 
SecurityType(sector='Comdty', name='Financial commodity option.') 
... 
SecurityType(sector='Muni', name='ZERO COUPON, OID') 
SecurityType(sector='Pfd', name='PRIVATE') 
SecurityType(sector='Pfd', name='PUBLIC') 
SecurityType(sector='', name='') 
SecurityType(sector='', name='') 
SecurityType(sector='', name='') 
SecurityType(sector='', name='') 
SecurityType(sector='', name='') 
SecurityType(sector='', name='') 
SecurityType(sector='', name='') 
SecurityType(sector='', name='') 
SecurityType(sector='', name='') 

最后线出现得空的元组;原来的确只有一行逗号。

+0

请参阅上面的说明 - 虽然这*应该*工作,我不认为它实际上,由于错误。 – DSM 2013-05-04 13:56:56

+0

@DSM:错误已解决;这在3.3.1中适用于我。运行OP示例时,我没有任何问题。 – 2013-05-04 13:59:53

相关问题