给Python新手的一道面试题:如何正确读写文件

开发 开发工具
读写文件时,应该考虑的问题包括:字符编码问题,操作完文件要即时关闭文件描述符,同时还要注意代码的兼容性。

 

[[203305]]

这是我司前段时间招人笔试中一道比较简单题,面向初中级程序员,不过很少有人能回答完整的,问题本身不难,主要还是考察动手能力和基本代码功,准备找工作的先收藏留着以后用得着。

看题:请指出下面代码段中的错误

  1. >>> f = open("test.txt", mode="w"
  2. >>> f.write(u"python之禅") 

分析:Python 提供了内建函数 open 用于读写文件,函数返回一个文件对象,可对文件进行读、写操作,用参数 mode 来控制。

默认是读文件

  1. >>> f = open("test.txt") 
  2. >>> f.read() 
  3. python之禅 

上面这段代码如果在python2中运行,会报错:

  1. Traceback (most recent call last): 
  2. File ““, line 1, in 
  3. UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 6-7: ordinal not in range(128) 

这是一个字符编码的问题,编码错误是Python程序员最经常遇到的错误,之前在公众号中写过关于编码错误的原因。

之所以报错是程序没法直接保存 unicode 字符串,要经过编码转换成而 str 类型的二进制字节序列才能够保存。

write 方法会自动帮你做编码转换,默认使用 ascii 编码格式,因为 ascii 字符集不能处理中文,所以出现了 UnicodeEncodeError 错误。

正确的方式是在调用 write 之前手动用 utf-8 或者 gbk 编码转换成 str 类型。

  1. >>> f = open("test.txt", mode="w"
  2. >>> content = u"Python之禅" 
  3. >>> contentcontent = content.encode(encoding='utf-8'
  4. >>> f.write(content) 

第二个问题是文件对象没有正常关闭,有人可能要问了,不关闭会有什么影响,操作完文件时,如果不关闭文件,那么将对系统造成资源浪费,因为系统可打开的文件描述符数量是有限制,比如 Linux 是 65536,所以必须要关闭文件。

  1. >>> f = open("test.txt", mode="w"
  2. >>> content = u"Python之禅" 
  3. >>> contentcontent = content.encode(encoding='utf-8'
  4. >>> f.write(content) 
  5. >>> f.close() 

close 就万事大吉了吗?未必。

因为有可能在调用 open 函数的时候就报错了,比如因为权限问题没法在该目录读写文件,此时,文件对象都没创建成功,调用close肯定会报错。

再比如在第4行 write 的时候有可能报错,因为磁盘空间不足,这个时候报错了, close 方法就没有机会执行了。

正确地做法是用 try except 对异常进行捕获。注意,open 函数要在 try 代码块外面

  1. f = open("output.txt", "w") 
  2. try: 
  3.    content = u"Python之禅" 
  4.    f.write(content.encode(encoding='utf-8')) 
  5. except IOError as e: 
  6.     print("oops, %s" % e.args[0]) 
  7. finally: 
  8.     f.close() 

不过,更优雅的写法是用 with ... as 写法,因为 文件对象实现了上下文管理器协议,程序进入 with 语句块时,会把文件对象赋值给变量 f,在程序退出 with 语句块的时候会地自动调用 close 方法。

  1. with open("output.txt", "w") as f: 
  2.      content = u"Python之禅" 
  3.     f.write(content.encode(encoding='utf-8')) 

***还有一个问题是兼容性,python2 与python3 的 open 函数不一样,后者可以在函数中指定字符编码格式,而 python2 则没有。

  1. # python3 
  2.  
  3. with open("output.txt", "w", encoding="utf-8") as f: 
  4.      content = u"Python之禅" 
  5.     f.write(content) 

那么如何写出同时兼容2和3的open函数呢?

没错,使用 io 模块下的 open 函数,python2 中的 io.open 等价于 python3 中的 open 函数,可以指定 encoding 参数,同时 python3 也保留有 io.open 函数

  1. from  io import open 
  2. with open("output.txt", "w", encoding='utf-8') as f: 
  3.     f.write(u"python之禅") 

【本文是51CTO专栏作者“刘志军”的原创文章,作者微信公众号:Python之禅(VTtalk)】

戳这里,看该作者更多好文

责任编辑:赵宁宁 来源: 51CTO专栏
相关推荐

2011-05-23 11:27:32

面试题面试java

2018-03-06 15:30:47

Java面试题

2009-08-11 10:12:07

C#算法

2023-02-04 18:24:10

SeataJava业务

2009-08-11 14:59:57

一道面试题C#算法

2021-05-31 07:55:44

smartRepeatJavaScript函数

2017-11-21 12:15:27

数据库面试题SQL

2009-08-11 15:09:44

一道面试题C#算法

2022-04-08 07:52:17

CSS面试题HTML

2023-08-01 08:10:46

内存缓存

2021-03-16 05:44:26

JVM面试题运行时数据

2021-10-28 11:40:58

回文链表面试题数据结构

2022-02-08 18:09:20

JS引擎解析器

2017-03-10 09:33:16

JavaScript类型

2015-09-02 14:09:19

面试题程序设计

2011-03-02 10:58:16

SQL server入门面试题

2011-06-14 09:12:03

JavaScript

2021-03-27 10:59:45

JavaScript开发代码

2018-02-01 16:26:44

面试题static变量

2018-04-26 11:23:01

Linuxfork程序
点赞
收藏

51CTO技术栈公众号