2013-05-04 100 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

相關問題