Python中的文件操作

Posted by JustDoDT on January 13, 2018

1. 文件的概述

为啥需要文件?

因为文件可以持久化的存储到磁盘中。

2. 文件的操作

2.1 文件的打开

In [1]: file = open('test.txt','r')
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-1-972ee8ded49c> in <module>()
----> 1 file = open('test.txt','r')

FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'

In [2]: file = open('test.txt','r')   # 打开已经存在的文件



In [11]: file = open('/home/pyvip/file/t','r')
In [12]: file.open()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-12-ea830c264d44> in <module>()
----> 1 file.open()

AttributeError: '_io.TextIOWrapper' object has no attribute 'open'

In [13]: file = open(r'/home/pyvip/file/t','r') #r是表示取消转义,当文件出现/t,/n等的时候

In [14]: file.read()
Out[14]: 'hahahahha\n'

往test.txt中写入hello world,用read()方法,发现读出来的是空的内容。这是为什么呢?

因为,就好像你在Windows中一样,在文件中写入了东西,没有保存,即无法读取你新加入的内容。

python中要想读取到新增的文件内容,必须要把以前的文件给关闭,然后再读取。

In [6]: file.close()
In [7]: file = open('test.txt','r')
In [8]: file.read()
Out[8]: 'hello world\n'    # 以换行符的形式打印

注意:打开了文件一定要进行关闭。

2.2 文件的写操作

2.2.1 write
In [16]: file = open('test.txt','w')
In [17]: file.write('xxxXXXXXXXX\naaaaa\nbbbbbbbb')
Out[17]: 26
# w 是往文件中写入字符的,26是表示写入了26个字符(包含换行符)。   

注意:虽然w可以往文件中写入东西,但是他会把以前的文件内容给覆盖掉,只保留最新写入的内容;如果没有这个文件,她会自动创建一个文件。

2.2.2 writelines
In [27]: file = open('test.txt','w')

In [28]: file.writelines('hello')
In [29]: file.writelines(['hello','python','world'])

In [30]: file.close()
In [31]: file2 = open('test.txt','r')

In [32]: file2.read()
Out[32]: 'hellohellopythonworld'

writelines会把多个元素拼加到一起。

2.2.3 a 追加
In [34]: file = open('test.txt','a')   # a 表示追加,在以前的基础上追加新的内容。

In [35]: file.write('hhhhhhhhhhh')
Out[35]: 11

In [36]: file.flush()   # flush() 为刷盘,即保存。

In [37]: file = open('test.txt','r')

In [38]: file.read()
Out[38]: 'hellohellopythonworldhhhhhhhhhhh'

注意:在末尾追加,读的时候,读不出所有的内容。读的时候是从开始追加的位置向后读取的,如果要想全部读完,必须要先进行关闭了,再读取文件的内容。

In [40]: file = open('test.txt','r')

In [41]: file.read()
Out[41]: 'hellohellopythonworldhhhhhhhhhhh'

In [42]: file2 = open('test.txt','a')

In [43]: file2.write('世界您好\n你好啊\n哈哈哈')
Out[43]: 12

In [44]: file2.flush()

In [45]: file.read()
Out[45]: '世界您好\n你好啊\n哈哈哈'
    
# 要想读取文件所有的内容,需要把文件关闭了,再进行读取。
In [47]: file.close()
In [48]: file = open('test.txt','r')

In [49]: file.read()
Out[49]: 'hellohellopythonworldhhhhhhhhhhh世界您好\n你好啊\n哈哈哈'
2.2.4 readline()
# readline() 是一行一行的读取文件的内容
In [51]: file = open('test.txt','r')
In [52]: file.readline()
Out[52]: 'hellohellopythonworldhhhhhhhhhhh世界您好\n'
2.2.5 readlines()
# readlines()是返回的列表,并且列表中的元素换行
In [53]: file.close()
    
In [54]: file = open('test.txt','r')
In [55]: file.readlines()
Out[55]: ['hellohellopythonworldhhhhhhhhhhh世界您好\n', '你好啊\n', '哈哈哈']

小结: read是读取所有;readline是读取一行;readlines是读取所有,并且返回的是一个列表,列表的每个元素对应每一行。

思考:为啥会出现3种读的方法?

因为,如果文件过大,用read读取的话,是要把文件的所有内容加载到内存中,该操作是相当消耗内存的,由此得出了readline,一行一行的读取;readlines可以用于爬虫中。

2.2.6 tell() 和 seek()
In [56]: file.tell()     #tell()是当前文件指针的位置。
Out[56]: 64

In [57]: file.read()
Out[57]: ''

In [58]: file.seek(0)  #seek()是移动文件指针的位置。0表示移动到文件开头。
Out[58]: 0

In [59]: file.read()
Out[59]: 'hellohellopythonworldhhhhhhhhhhh世界您好\n你好啊\n哈哈哈'

3. 上下文管理器

with ,上下文管理器,自动保存关闭,不需要执行close()操作,as是重新赋值

In [60]: with open('test.txt','r') as file:
    ...:     print(file.read())
    ...:     
hellohellopythonworldhhhhhhhhhhh世界您好
你好啊
哈哈哈



# 通过这两个方法可以很方便的实现上下文管理;with会把__enter__的返回值赋给as后的变量。
import time
class RunTime:
    def __enter__(self):
        self.start_time = time.time()
        return self.start_time
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.end_time = time.time()
        self.run_time = self.end_time - self.start_time
        print(self.run_time)

with RunTime() as a:
    print(a)
    for i in range(10000000):
        pass

4. IO流

IO流,临时存储数据,对字符串、字节进行操作。

# 对字符串进行操作
In [61]: import io

In [62]: a = io.StringIO()  # 创建一个对象进行保存读取
In [63]: a.write('hello world')  # 写入数据
Out[63]: 11
In [64]: print(a.getvalue()) # 获取数据
hello world
In [65]: a.close()
    
# 对字节进行操作
In [68]: import io
In [69]: b = io.BytesIO(b'abcdefg')
In [70]: print(b.getvalue())
b'abcdefg'

5. OS模块

In [73]: import os  #os 模块会自动帮我们识别系统
In [74]: a = os.system('pwd')  # 直接调用系统命令
/home/pyvip

# 路径操作
In [76]: b = os.path.join('pyvip','justdodt','python')   # 路径拼接
In [77]: print(b)
pyvip/justdodt/python

# 新建文件夹
In [78]: os.mkdir('bigdata')
# 判断是否创建成功
In [81]: os.path.exists('/home/pyvip/bigdata/')
Out[81]: True

# 对文件夹重命名
In [82]: os.rename('bigdata','hahaha')
In [83]: os.path.exists('/home/pyvip/bigdata/')
Out[83]: False

In [84]: os.path.exists('/home/pyvip/hahaha/')
Out[84]: True

# 删除目录,但是只能删除不为空的目录
In [5]: os.rmdir(r'/home/pyvip/hahaha/')
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-5-c718629aad09> in <module>()
----> 1 os.rmdir(r'/home/pyvip/hahaha/')

OSError: [Errno 39] Directory not empty: '/home/pyvip/hahaha/'

6. shutil 模块

# 移动文件
In [85]: import shutil
In [86]: shutil.move(r'/home/pyvip/test.txt',r'/home/pyvip/hahaha/')
Out[86]: '/home/pyvip/hahaha/test.txt'
    
# 删除目录,也可以把目录下面的文件删除
In [87]: shutil.rmtree(r'/home/pyvip/hahaha/')
In [88]: os.path.exists(r'/home/pyvip/hahaha')
Out[88]: False

7. 文件的常用操作总结

avatar

8. 习题

根据以上的内容,自定义上下文管理器,判断IO操作和文件操作哪个速度更快。

import time,io
class RunTime:
    def __enter__(self):
        self.start_time = time.time()
        return self.start_time
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.end_time = time.time()
        self.run_time = self.end_time - self.start_time
        print(self.run_time)

iotest = io.StringIO()
iotest.write('外面的世界真精彩!')

with RunTime() as a:
   # IO 操作
   print('---------IO操作执行的时间-----------')
   print(iotest.getvalue())
   print('###################################')

with RunTime() as a:
    # 文件操作
    with open('/home/pyvip/test.txt') as f:
        print('-------文件操作执行的时间-----------')
        print(f.read())
        print('###################################')

执行上面代码的结果为:

py3env) pyvip@VIP:~$ python time.py 
-------IO操作执行的时间-----------
外面的世界真精彩!
##################################
0.0006020069122314453
-------文件操作执行的时间----------
外面的世界真精彩!

########################################