Python2/Python3通过writerow写入csv文件会有多余的空行 及 bytes和str互相转换

Table of Contents

前言

Python2代码

Python2原来代码【有问题的】

现象

问题分析

Python2解决办法

Python2完整代码

Tips: 追加写入csv

Python3代码:

方法一:writer加dialect='unix'

方法二:打开方式加newline=''

打印出当前操作系统的换行符

Python3为什么不能以bytes模式打开csv文件?

csv模块writerow函数代码

Python3以bytes模式打开csv文件

福利【重点】:bytes和str互相转换

总结:

文件打开模式


前言

项目需要,先处理txt文档,从中提取数值,然后将其转存为csv档来做数据分析。在存档为csv文件时出问题了,以下为我的经验总结,供各位参考。希望大家可以少走弯路。

Python2代码

Python2原来代码【有问题的】

#!/usr/bin/env python# -*- coding: utf-8 -*-import csvcsvRow = ['01:01:00', '33000', '27589', '27070', '27070', '25855']with open("test.csv","a+") as csvfile:writer = csv.writer(csvfile)for item in range(0, 3):writer.writerow(csvRow)

现象

用Notepad++打开档案(补上这个,怕有些朋友不会View->Show Symbol->Show All Characters ),发现每行末尾都有CR, CRLF,如下截图。

如果用Excel打开,两行中间会多出一空行,如下图:

问题分析

现在就要搞清楚CR, CRLF分别是谁输出的。本文后续会深入分析原因(楼梯在此方法二:打开方式加newline='')

心急的朋友可以先参考这个链接https://bugs.python.org/issue7198

Python2解决办法

将文档的打开方式改为二进制方式。

原来的打开方式:with open("test.csv","a+") as csvfile:

更改后打开方式:with open("test.csv","ab+") as csvfile:

Python2完整代码

如下供各位参考:

#!/usr/bin/env python# -*- coding: utf-8 -*-import csvcsvRow = ['01:01:00', '33000', '27589', '27070', '27070', '25855']with open("test.csv","ab+") as csvfile:writer = csv.writer(csvfile)for item in range(0, 3):writer.writerow(csvRow)

更新后文件图片,用Notepad++打开如下:

用Excel打开图片如下:

Tips: 追加写入csv

将文档的打开方式由w(写入)改为a(追加)方式。

Python3代码:

方法一:writerdialect='unix'

headerRow = ['ISN', 'BUILD_PHASE']oneRow = ['81E2-TESTTEST','PRE-PVT']with open("test.csv","a+") as csvfile:writer = csv.writer(csvfile, dialect='unix')    # 将dialect设置为unix,换行符即为'\n'writer.writerow(headerRow)writer.writerow(oneRow)

参考csv模块说明,有这么一段话

Readers and writers support a dialect argument, which is a convenient
handle on a group of settings.  When the dialect argument is a string,
it identifies one of the dialects previously registered with the module.
If it is a class or instance, the attributes of the argument are used as
the settings for the reader or writer:

    class excel:
        delimiter = ','
        quotechar = '"'
        escapechar = None
        doublequote = True
        skipinitialspace = False
        lineterminator = '\r\n'
        quoting = QUOTE_MINIMAL

笔者翻译:reader和writer都支持dialect参数,处理一组设置时会很方便。

当dialect参数是一个字符串时,它识别为模块先前注册的其中一种方言。

如果它是类或实例,则参数的属性被用来作为reader和writer的设置,如上面的class excel等。

例如,如果dialect参数为excel类时,换行符为’\r\n’.

如果dialect参数为unix, 换行符为’\n’【以下可参考csv模块说明文档】

class excel(Dialect):"""Describe the usual properties of Excel-generated CSV files."""delimiter = ','quotechar = '"'doublequote = Trueskipinitialspace = Falselineterminator = '\r\n'quoting = QUOTE_MINIMALregister_dialect("excel", excel)class excel_tab(excel):"""Describe the usual properties of Excel-generated TAB-delimited files."""delimiter = '\t'register_dialect("excel-tab", excel_tab)class unix_dialect(Dialect):"""Describe the usual properties of Unix-generated CSV files."""delimiter = ','quotechar = '"'doublequote = Trueskipinitialspace = Falselineterminator = '\n'quoting = QUOTE_ALLregister_dialect("unix", unix_dialect)

方法二:打开方式加newline=''

headerRow = ['ISN', 'BUILD_PHASE']oneRow = ['81E2-TESTTEST','PRE-PVT']# 大家可以将换行符指定为'\n'或'\r'或者不指定,试试效果with open("test.csv","a+", newline='') as csvfile:  #换行符指定为空字符,不是None【空字符!=None】writer = csv.writer(csvfile)writer.writerow(headerRow)writer.writerow(oneRow)

以下这段话选择builtins.py模块中open函数:

On output, if newline is None, any '\n' characters written are translated to the system default line separator, os.linesep. If newline is '' or '\n', no translation takes place. If newline is any of the other legal values, any '\n' characters written are translated to the given string.

笔者翻译:在输出时,如果换行是None,则写入的任何'\ n'字符都被转换为系统默认行分隔符,os.linesep。 如果换行符是''或'\ n',不进行转换。 如果换行符是任何其他合法值【注意:不能将其随心所意地设置为其他英文字母,大家可以自行实验】,所有'\ n'字符都将被转换为给定的字符串。

如果newline采用默认值None(即不进行指定任何指定),在Windows系统下,os.linesep即为'\r\n',那么此时就会将’\n’转换为’\r\n’(即CRLF),所以会多一个’\r’(回车)出来,如下图。在csv中打开就会多一行。

打印出当前操作系统的换行符

import osprint("os.linesep:%r" %os.linesep)

Python3为什么不能以bytes模式打开csv文件?

有朋友会问:为什么不能像Python2那样,将open方式加个b不就好了吗?

在内置模块builtins.py中open函数中有这么一段话:

Python distinguishes between files opened in binary and text modes,

even when the underlying operating system doesn't. Files opened in

binary mode (appending 'b' to the mode argument) return contents as

bytes objects without any decoding. In text mode (the default, or when

't' is appended to the mode argument), the contents of the file are

returned as strings, the bytes having been first decoded using a

platform-dependent encoding or using the specified encoding if given.

笔者翻译过来就是:

Python区分文件的打开方式:二进制模式和文本模式,

即使底层操作系统没有作此区分。 以二进制模式打开的文件

(mode参数要加'b')返回内容为不用解码的bytes对象。

在文本模式下(默认情况,或者mode参数加了't'),文件的内容返回为

string对象--使用操作系统平台的编码或使用指定的编码(如果给定)来将bytes先解码。

简单而言:

Python3有两种表示字符序列的类型:bytes和str。bytes即为原始的8位值,即纯8位值。str包含Unicode字符。

Python3给open函数添加了名为encoding的新参数,其默认值为’utf-8’,文件的默认打开方式为文本模式。如果像如下这句代码加个’b’来以二进制打开,那么写入时会提示错误“a bytes-like object is required, not 'str'”,因为writerow写入的是字符串格式【这个可以参考csv模块下的writerow函数代码】。

# Python3为什么不能以bytes模式打开csv文件?【请注意:如下代码执行会出错】headerRow = ['ISN', 'BUILD_PHASE']oneRow = ['81E2-TESTTEST','PRE-PVT']with open("test.csv","ab+") as csvfile: # 打开方式为bytes模式,下面写入会出错writer = csv.writer(csvfile)writer.writerow(headerRow)writer.writerow(oneRow)

csv模块writerow函数代码

【怕某些朋友找不到,贴上csv模块writerow函数代码,注意这句“if isinstance(item, text_type):”判断item是否为text_type。

如果是text_type,才会执行下面encode(编码)语句。如果不是,那就不会被写入csv。】

class CSVWriter(CSVBase):def __init__(self, fn, **kwargs):self.stream = _csv_open(fn, 'w')self.writer = csv.writer(self.stream, **self.defaults)def writerow(self, row):if sys.version_info[0] < 3:r = []for item in row:if isinstance(item, text_type):item = item.encode('utf-8')r.append(item)row = rself.writer.writerow(row)

Python3以bytes模式打开csv文件

# Python3可以以bytes模式打开csv文件# 只是这时写入的数据格式为bytes,string格式需要利用encode编码为bytes对象strTest = 'ISN'with open("test.csv","ab+") as csvfile: # 打开方式为bytes模式csvfile.write(os.urandom(10))csvfile.write(strTest.encode())

福利【重点】:bytes和str互相转换

之前说了Python3的两种字符表示类型:bytes和str。我们在编写Python程序时,核心部分应该只处理Unicode类型,编码和解码操作应该放在外围。下面的两个辅助函数来自《Effective Python》,个人觉得很好,特分享给大家。

def to_str(bytes_or_str):"""接受str或bytes,总是返回str:param bytes_or_str::return: Instance of str"""if isinstance(bytes_or_str, bytes):value = bytes_or_str.decode('utf-8')else:value = bytes_or_strreturn value    # Instance of strdef to_bytes(bytes_or_str):"""接受str或bytes,总是返回bytes:param bytes_or_str::return: Instance of bytes"""if isinstance(bytes_or_str, str):value = bytes_or_str.encode('utf-8')else:value = bytes_or_strreturn value    # Instance of bytes

总结:

虽然是一个小问题,但是涉及到一些csv基本知识点,以及Python2与Python3的区别。希望各位看官可以明白。

文件打开模式

文件打开模式之间的区别可以参考如下链接:

Python File(文件) 方法_文件打开模式_mode参数

(0)

相关推荐

  • Python正则表达式,这一篇就够了

    大多数编程语言的正则表达式设计都师从Perl,所以语法基本相似,不同的是每种语言都有自己的函数去支持正则,今天我们就来学习 Python中关于 正则表达式的函数. re模块主要定义了9个常量.12个函 ...

  • (2条消息) python 本地数据获取

    在python中需要长期保存的本地数据都以文件的方式存在,所以获取本地数据其实就是从文件中读取数据. 打开文件的方法如下: 参数一是必须的,表示文件的存储路径.参数二是文件的打开模式,是可选的,默认值 ...

  • 可视化正则表达式教程

    本文已经原作者 Amit Chaudhary 授权翻译. 在NLP中,根据模式检查文本或从文本中提取与特定模式匹配的内容是常见的任务.正则表达式是实现这一点的强大帮手. NLP (Natural La ...

  • Python 全套教程 学习笔记

    Python 全套教程 学习笔记 Python 全套教程 学习笔记 print()函数 转义字符 二进制与字符编码 Python中的标识符和保留字 变量的定义和使用 数据类型 数据类型转换 Pytho ...

  • 第93天:文件读写

    文件操作中最基本的当然属于文件的读写操作.当我们利用爬虫抓取到一堆数据时,就需要进行文件写操作,将数据写入到文件当中:当我们需要对抓取到的文件内容进行筛选,获取有效信息时,需要对文件进行读操作.本文将 ...

  • Python中的文件处理–为初学者学习Python文件处理

    Python文件处理操作 Python文件处理操作(也称为Python I / O)处理两种类型的文件.他们是: 文字档 二进制文件 即使两种文件类型在表面上看起来相同,它们对数据的编码也不同. 文本 ...

  • 【读码】将数据写入csv文件示例

    将数据保存到csv中常用的有这三种,之前我写爬虫保存数据到csv时都只是使用其中的一种方法.今天列出三段代码,大家阅读阅读. code1:以行的方式批量写入 import csv with open( ...

  • 如何解决Python3写入CSV出现 gbk codec cannot encode的错误?

    今天,我在 Windows 上用 Python3 爬取知乎上有关中医的问答,但是在把爬取的内容写进CSV文件的时候,出现了以下异常. UnicodeEncodeError: 'gbk' codec c ...

  • Python写的csv文件,如何让 Excel 双击打开不乱码?

    我们常常需要在 Python 中输出 CSV 文件,但你可能会发现,这些输出的 CSV文件,不能双击使用 Excel 打开,否则中文会变成乱码.例如下面这段代码: 登录后复制 import panda ...

  • CSV文件打开后数字变成了科学计数且15位之后的数字都变为0了,怎么破?

    图 1 图 2 Excel单元格数字有一定的规范与限制,如同做人也有底线和原则一样,如果数字超过11位就会自动显示科学计数,如果超过15位就无效,即15位以后的数字不管输入多少位都显示0,可是数字必须 ...

  • 批量汇总CSV文件数据,怎么只剩一列数据了?

    这是群里一个朋友的提问,算是一个大家可能会遇到的坑,可以了解一下.即: 在用Power Query批量汇总CSV文件数据时,自定义写公式解析文件,结果展开时,只有一列数据: 对于这个问题,一般情况下是 ...

  • C#_.net core 3.0自定义读取.csv文件数据_解决首行不是标题的问题_Linqtocsv改进

    linqtocsv文件有不太好的地方就是:无法设置标题的行数,默认首行就是标题,这不是很尴尬吗?   并不是所有的csv文件严格写的首行是标题,下面全是数据,我接受的任务就是读取很多.csv报表数据, ...

  • python笔记5-python2写csv文件中文乱码问题

    前言 python2最大的坑在于中文编码问题,遇到中文报错首先加u,再各种encode.decode. 当list.tuple.dict里面有中文时,打印出来的是Unicode编码,这个是无解的. 对 ...

  • httprunner学习28-yaml文件 参数化读取 csv 文件字符串转 int

    前言 使用 httprunner 框架参数化时,一般参数数据放csv文件,csv 文件默认都是字符串类型,有些接口需传 int 类型的数字. 当读取csv文件的数据后,需进行数据转换,参考前面一篇ht ...

  • 利用puppeteer采集百度数据,并写入json文件

    利用puppeteer采集百度数据,并写入json文件 代码篇,属于日常采集篇,后期会mongdb来存贮数据 const puppeteer = require("puppeteer&quo ...