[Python]cherrypy环境下生成csv文件,提供下载

来源:互联网 发布:playclub陈诗涵mod数据 编辑:程序博客网 时间:2024/06/05 06:10

有如下格式的数据需要输出到csv,数据示例:

invoices = [{‘id’: 1451L, ‘note’: ‘ABC’, ‘payout’: 1.1, ‘profit’: 0.25},
{‘id’: 1452L, ‘note’: ‘QWE’, ‘payout’: 1512.66, ‘profit’: 179.39}]

fieldnames = [‘id’, ‘note’, ‘payout’, ‘profit’]

1.字符串手动csv

csv文件使用“,”作为分割符,也就是输出的.csv文件中,“,”会被作为列间隔来解析

1.首先拼出表头

# 输出BOM头,使得文件被打开的时候以UTF-8解析header = '\xEF\xBB\xBF' + '\n'header += ','.join(fieldnames) + '\n'

2.拼出数据部分

    content = ''    for invoice in invoices:        values = ','.join([str(invoice[field]) for field in fieldnames]) + '\n'        content += values    csv_data = header + content

3. 设置cherrypy response header

cherrypy.response.headers.update({'Content-Type': 'application/octet-stream',                                  'Content-Disposition': 'attachment; filename=%s' % csv_name})

把csv_data作为response的body返回, 其中filename参数为文件名,也就是浏览器下载该文件后保存的文件名称

2.使用csv module生成csv

1.csv.writer

csv.writer(),接受一个以‘b’模式打开的文件对象作为参数, 可以指定csv文件的分隔符
csv.writerow(),接受iteratable作为参数,比如list,tuple, 一次输出一行
csv.writerows(), 一次输入多行

import csvwith open('eggs.csv', 'wb') as csvfile:    spamwriter = csv.writer(csvfile, delimiter=' ',                            quotechar='|', quoting=csv.QUOTE_MINIMAL)    spamwriter.writerow(['Spam'] * 5 + ['Baked Beans'])    spamwriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])    spamwriter.writerows([('a1', 'b1', 'c1'),('a2', 'b2', 'c2')])

2.csv.DictWriter

csv的这些函数其实已经可以满足我们的需求,但是对于我们已经是list of dict 的数据,也是有现成的结构可以用的:csv.DictWriter

csv.DictWriter(csvfile, fieldnames, restval=”, extrasaction=’raise’, dialect=’excel’, *args, **kwds)

csvfile: 以wb打开的文件对象
fieldnames:你要输出的字段,也就是csv中的表头

官方Example:

import csvwith open('names.csv', 'w') as csvfile:    fieldnames = ['first_name', 'last_name']    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)    writer.writeheader()    # 输出设置好的表头     writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})    writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})    writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})

我们这样使用,生成临时文件,前端得到文件路径,直接下载:

关于windows中文编码:
这里写图片描述

生成csv:

    # window7默认为cp936编码(GBK),和gb2312的关系太销魂,    # 不过可以认为对于中文,他们都支持.    # encoding指定输出文件的编码,一般输出UTF-8,如果有中文,    # 在Excel中不一定能打开(对于Excel2007,如果装了补丁可以正常显示中文,    # 如果没装,中文显示将会是乱码,对于Excel2010对中文支持正常),    # 为了能够支持中文,设置为gb2312编码,其实设置成gbk,cp18030等编码方式都可以,    # 如果输出的还有比较诡异的字符,使用gb2312应该也显示不了,    # 如果需求要支持中文,并且Excel中打开可以使用gb2312,    # 如果中文不是那么重要,建议还是utf-8编码.    with codecs.open('/tmp/' + csv_name, 'w', encoding="gb2312") as csvfile:        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)        writer.writeheader()        for invoice in invoices:            writer.writerow(invoice)

前端下载:

<script type="text/javascript">$(document).ready(function(){    $('button[data-role=generate_csv_gb2312]').on('click', function(){        $.ajax({url: '/invoice/generate_invoice_csv_gb2312?role={{role}}',                type: 'GET',                error: function(){                    alert('generate error.');                },                success: function(e){                    window.open(e.url);                    history.go(-1);                }            })    })})</script>

原始数据:
这里写图片描述

生成csv文件:
这里写图片描述

3.BOM(byte order mark)

在UTF-8,UTF-16和UTF-32编码的文件中,BOM是用来标示字节顺序的,打开文件的时候BOM字节是会被跳过的,不会当做文件内容解析,对于输出UTF-8的文件,可以在输出文件的头部写入:

\xEF\xBB\xBF
也就是codecs.BOM_UTF8

Python中编码支持的BOM如下:
codecs.BOM
codecs.BOM_BE
codecs.BOM_LE
codecs.BOM_UTF8
codecs.BOM_UTF16¶
codecs.BOM_UTF16_BE
codecs.BOM_UTF16_LE
codecs.BOM_UTF32
codecs.BOM_UTF32_BE
codecs.BOM_UTF32_LE

On encoding a UTF-8 encoded BOM will be prepended to the UTF-8 encoded bytes. For the stateful encoder this is only done once (on the first write to the byte stream). For decoding an optional UTF-8 encoded BOM at the start of the data will be skipped.

Example:
生成带BOM_UTF8的文件

f = codecs.open('ufile.log', 'w', 'utf_8_sig')

把带BOM的UTF-8的文件转换为不带BOM的UTF-8文件

with open('file_with_utf8_bom.txt') as fp:    s = fp.read()    string_read_from_file = s.decode('utf_8_sig ') # 从带有utf-8签名的文件中读出字符串    string_without_utf8_bom = string_read_from_file.encode('utf_8')     # 编码为utf-8,把string_without_utf8_bom直接写入的文件则不带BOM_UTF8(\xEF\xBB\xBF)

4.References:

1.https://docs.python.org/2/library/codecs.html
2.http://stackoverflow.com/questions/8898294/convert-utf-8-with-bom-to-utf-8-with-no-bom-in-python
3.https://docs.python.org/2/library/codecs.html#module-encodings.utf_8_sig
4.http://segmentfault.com/q/1010000002493464/a-1020000002493529

0 0
原创粉丝点击