2011-10-02 79 views
3

我试图从morningstar下载CSV内容,然后解析其内容。如果我直接将HTTP内容注入到Python的CSV解析器中,结果格式不正确。但是,如果我将HTTP内容保存到文件(/tmp/tmp.csv)中,然后在python的csv分析器中导入文件,则结果是正确的。换句话说,为什么:将CSV直接下载到Python CSV解析器

def finDownload(code,report): 
    h = httplib2.Http('.cache') 
    url = 'http://financials.morningstar.com/ajax/ReportProcess4CSV.html?t=' + code + '&region=AUS&culture=en_us&reportType='+ report + '&period=12&dataType=A&order=asc&columnYear=5&rounding=1&view=raw&productCode=usa&denominatorView=raw&number=1' 
    headers, data = h.request(url) 
    return data 

balancesheet = csv.reader(finDownload('FGE','is')) 
for row in balancesheet: 
    print row 

回报:代替

['F'] 
['o'] 
['r'] 
['g'] 
['e'] 
[' '] 
['G'] 
['r'] 
['o'] 
['u'] 
    (etc...) 

[Forge Group Limited (FGE) Income Statement'] 

回答

9

这个问题是由一个文件迭代逐行完成,而一个字符串迭代逐字符完成的。

你想StringIO/cStringIO(Python的2)或io.StringIO(Python 3中,感谢约翰·马金指着我),这样一个字符串可以被当作一个类文件对象:

的Python 2:

mystring = 'a,"b\nb",c\n1,2,3' 
import cStringIO 
csvio = cStringIO.StringIO(mystring) 
mycsv = csv.reader(csvio) 

Python 3中

mystring = 'a,"b\nb",c\n1,2,3' 
import io 
csvio = io.StringIO(mystring, newline="") 
mycsv = csv.reader(csvio) 

两者都会在引用字段内正确地保留换行符:

>>> for row in mycsv: print(row) 
... 
['a', 'b\nb', 'c'] 
['1', '2', '3'] 
+1

“splitlines”是否也从Python 3中消失?我一直比'split'('\ n')'更喜欢它,因为我患有反胃恐惧症。 – PaulMcG

+0

@保罗:不,那也可以。好点子。 –

+0

-3'csvstring'是列表的烂名。通常CSV文件具有CR LF作为行分隔符;不要使用'mystring.split('\ n')',使用'mystring.splitlines()'。 'StringIO'没有“消失”,它已经重新定位到'io'模块并被重命名为'BytesIO'。还有一个可以在py3k'str'对象上使用的'StringIO'。请参阅http://docs.python.org/py3k/library/io.html#module-io –