convert_types.py 脚本中保存了一个列表,列表中存放的是pv行为,如:[‘离线动作-列表页-到这里去 1’,’离线动作-图区-搜周边 2’,’离线动作-图区-到这里去 1’…]

今天想要将 convert_types.py 里的pv行为全部都放在excel表里,行为名称和行为编号分开存放,于是使用pandas 中的dataframe结构存放数据,再将dataframe的数据写入excel文件中,代码写好后运行程序却报了以下错误:

1
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 7: ordinal not in range(128)

查阅资料后解决了以下两个问题

dataframe 如何写入数据到excel 文件中

单个dataframe 写入数据到excel 文件中

将整个dataframe 写入excel 文件,直接调用dataframe的to_excel()函数即可

1
2
3
# result 为结果列表,将列表转化为DataFrame类型数据
df = pd.DataFrame(result)
df.to_excel('filePath',sheet_name='sheetname')

to_excel()参数解释:

1
2
3
4
5
DataFrame.to_excel(excel_writer, sheet_name='Sheet1', na_rep='',
float_format=None, columns=None, header=True, index=True,
index_label=None, startrow=0, startcol=0, engine=None,
merge_cells=True, encoding=None, inf_rep='inf', verbose=True,
freeze_panes=None)

excel_writer : 字符串或ExcelWriter 对象——文件路径或现有的ExcelWriter

sheet_name :字符串,默认“Sheet1”——将包含DataFrame的表的名称。

na_rep : 字符串,默认‘ ’——缺失数据表示方式

float_format : 字符串,默认None——格式化浮点数的字符串

columns : 序列,可选——要编写的列

header : 布尔或字符串列表,默认为Ture。——写出列名。如果给定字符串列表,则假定它是列名称的别名。

index :布尔,默认的Ture——写行名(索引)

index_label : 字符串或序列,默认为None。——如果需要,可以使用索引列的列标签。如果没有给出,标题和索引为true,则使用索引名称。如果数据文件使用多索引,则需使用序列。

startrow :——左上角的单元格行来转储数据框

startcol :——左上角的单元格列转储数据帧

engine : 字符串,默认没有——使用写引擎-也可以通过选项io.excel.xlsx.writer,io.excel.xls.writer和io.excel.xlsm.writer进行设置。

merge_cells : 布尔,默认为Ture——编码生成的excel文件。只有xlwt需要,其他编写者本地支持unicode。

inf_rep : 字符串,默认“正”——无穷大的表示(在Excel中不存在无穷大的本地表示)

freeze_panes : 整数的元组(长度2),默认为None。——指定要冻结的基于1的最底部行和最右边的列

多个DataFrame 分为多个表写入同一个excel 文件中

需要通过ExcelWriter()方法打开一个已经存在的excel表格作为writer,然后通过to_excel()方法将需要保存的数据逐个写入excel,最后关闭writer

1
2
3
4
5
6
write = pd.ExcelWriter('filePath')
df = pd.DataFrame(result)
df1 = df.copy()
df.to_excel(write, sheet_name='data1')
df1.to_excel(write, sheet_name='data2')
write.save()

结果为excel 表中有表名为’data1’和’data2’的两张小表

多个DataFrame 写入一个excel 文件同一个表中

数据定义与上一个相同,只不过需要更改to_excel()函数中的参数而已

1
2
3
4
5
6
write = pd.ExcelWriter('filePath')
df = pd.DataFrame(result)
df1 = df.copy()
df.to_excel(write, sheet_name='data',startrow = 10)
df1.to_excel(write, sheet_name='data', startrow = 30, startcol = 10)
write.save()

df数据从表格的第十行开始插入

df1数据从表格的第三十行和第十列开始插入

注意第二个数据插入的地方不能有其他数据,否则数据会覆盖。

sys.setdefaultencoding(‘utf-8’)的使用

Python 里面的编码和解码也就是 unicode 和 str 这两种形式的相互转化。编码是 unicode -> str,相反的,解码就是 str -> unicode。剩下的问题就是确定何时需要进行编码或者解码了。

关于文件开头的”编码指示”,也就是 # -*- coding: -*- 这个语句。Python 默认脚本文件都是 UTF-8 编码的,当文件中有非 UTF-8 编码范围内的字符的时候就要使用”编码指示”来修正。关于 sys.defaultencoding,这个在解码没有明确指明解码方式的时候使用。

1
2
3
4
5
#! /usr/bin/env python 
# -*- coding: utf-8 -*-
# 注意这里的 s 是 str 类型的,而不是 unicode
s = '中文'
s.encode('gb18030')

这句代码将 s 重新编码为 gb18030 的格式,即进行 unicode -> str 的转换。因为 s 本身就是 str 类型的,因此 Python 会自动的先将 s 解码为 unicode ,然后再编码成 gb18030。因为解码是python自动进行的,我们没有指明解码方式,python 就会使用 sys.defaultencoding 指明的方式来解码。很多情况下 sys.defaultencoding 是
ANSCII,如果 s 不是这个类型就会出错。拿上面的情况来说,sys.defaultencoding 是 anscii,而 s 的编码方式和文件的编码方式一致,是 utf8 的,所以出错了:

1
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

出现这种情况时有两种方法来解决:

明确的指示出 s 的编码方式

1
2
3
4
5
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# 注意这里的 s 是 str 类型的,而不是 unicode
s = '中文'
s.decode('utf8').encode('gb18030')

先用 utf-8 解码,再用 gb18030 编码,就不会出错了

更改 sys.defaultencoding 为文件的编码方式

1
2
3
4
5
6
7
8
9
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

# 注意这里的 s 是 str 类型的,而不是 unicode
s = '中文'
s.encode('gb18030')

这是个固定用法,Python2.5 初始化后删除了 sys.setdefaultencoding 方法,所以需要重新载入 sys

dataframe.read_excel()

顺带说一下使用dataframe读取excel文件的方法

1
read_excel(io, sheetname=0, header=0, skiprows=None, skip_footer=0, index_col=None,names=None, parse_cols=None, parse_dates=False,date_parser=None,na_values=None,thousands=None, convert_float=True, has_index_names=None, converters=None,dtype=None, true_values=None, false_values=None, engine=None, squeeze=False, **kwds)

常用参数解析:

  • io : string, path object ; excel 路径。
  • sheetname : string, int, mixed list of strings/ints, or None, default 0 返回多表使用sheetname=[0,1],若sheetname=None是返回全表 注意:int/string 返回的是dataframe,而none和list返回的是dict of dataframe
  • header : int, list of ints, default 0 指定列名行,默认0,即取第一行,数据为列名行以下的数据 若数据不含列名,则设定 header = None
  • skiprows : list-like,Rows to skip at the beginning,省略指定行数的数据
  • skip_footer : int,default 0, 省略从尾部数的int行数据
  • index_col : int, list of ints, default None指定列为索引列,也可以使用u’strings’
  • names : array-like, default None, 指定列的名字。

附上完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#! /usr/bin/env python
# -*- coding=utf-8 -*-
import pandas as pd
import convert_types
import sys
reload(sys)
sys.setdefaultencoding('utf8')

key = []
value = []
list = convert_types.list
for i in range(len(list)):
key.append(list[i].strip().split('\t')[0])
value.append(list[i].strip().split('\t')[1])

result={"名称":key, "数值":value}

df = pd.DataFrame(result)
df.to_excel('/Users/v_huruijie/Documents/sug/sug.xlsx',sheet_name='convert_types.py')