天天看點

第十二章 Python檔案操作

12.1 open()

open()函數作用是打開檔案,傳回一個檔案對象。

用法格式:open(name[, mode[, buffering[,encoding]]]) -> file object

name 檔案名

mode 模式,比如以隻讀方式打開

buffering 緩沖區

encoding 傳回資料采用的什麼編碼,一般utf8或gbk

<b>mode</b>

<b>description</b>

r

隻讀,預設

w

隻寫,打開前清空檔案内容

a

追加

a+

讀寫,寫到檔案末尾

w+

可讀寫,清空檔案内容

r+

可讀寫,能寫到檔案任何位置

rb

二進制模式讀

wb

二進制模式寫,清空檔案内容

例如:打開一個檔案

&gt;&gt;&gt; f = open('test.txt', 'r')

&gt;&gt;&gt; f.

f.__class__(         f.__new__(           f.encoding           f.readinto(

f.__delattr__(       f.__reduce__(        f.errors             f.readline(

f.__doc__            f.__reduce_ex__(     f.fileno(            f.readlines(

f.__enter__(         f.__repr__(          f.flush(             f.seek(

f.__exit__(          f.__setattr__(       f.isatty(            f.softspace

f.__format__(        f.__sizeof__(        f.mode               f.tell(

f.__getattribute__(  f.__str__(           f.name               f.truncate(

f.__hash__(          f.__subclasshook__(  f.newlines           f.write(

f.__init__(          f.close(             f.next(              f.writelines(

f.__iter__(          f.closed             f.read(              f.xreadlines(

open()函數打開檔案傳回一個檔案對象,并賦予周遊f,f就擁有了這個檔案對象的操作方法。

<b>方法</b>

<b>描述</b>

f.read([size])

讀取size位元組,當未指定或給負值時,讀取剩餘所有的位元組,作為字元串傳回

f.readline([size])

從檔案中讀取下一行,作為字元串傳回。如果指定size則傳回size位元組

f.readlines([size])

讀取size位元組,當未指定或給負值時,讀取剩餘所有的位元組,作為清單傳回

f.write(str)

寫字元串到檔案

f.writelines(seq)

寫序列到檔案,seq必須是一個可疊代對象,而且要是一個字元串序列

f.seek(offset[, whence=0])

在檔案中移動檔案指針,從whence(0代表檔案起始位置,預設。1代表目前位置。2代表檔案末尾)偏移offset個位元組

f.tell()

傳回目前在檔案中的位置

f.close()

關閉檔案

f.flush

重新整理緩沖區到磁盤

部落格位址:http://lizhenliang.blog.51cto.com and https://yq.aliyun.com/u/lizhenliang

qq群:323779636(shell/python運維開發群)

<b>12.2 檔案對象操作</b>

寫一個測試檔案test.txt舉例:

# cat test.txt

1.python

2.java

3.c++

4.ruby

12.2.1 read()讀取所有内容

&gt;&gt;&gt; f.read()

'1.python\n2.java\n3.c++\n4.ruby\n'

# 擷取指定位元組

 指定讀取多少位元組:

&gt;&gt;&gt; f.read(9)

'1.python\n'

12.2.2 readline()讀取下一行内容

&gt;&gt;&gt; f.readline()

'2.java\n'

12.2.3 readlines()讀取所有内容傳回一個清單

&gt;&gt;&gt; f.readlines()

['1.python\n', '2.java\n', '3.c++\n', '4.ruby\n']

12.2.4 wirte()寫入字元串到檔案

&gt;&gt;&gt; f = open('test.txt', 'a')  # 以追加方式打開檔案

&gt;&gt;&gt; f.write("5.shell\n")  # 這一步并沒有真正寫到檔案

&gt;&gt;&gt; f.flush()  # 重新整理到磁盤才寫到檔案

5.shell

12.2.5 wirtelines()寫入一個序列字元串到檔案

&gt;&gt;&gt; f = open('test.txt', 'a')

&gt;&gt;&gt; f.writelines(['a','b','c'])

&gt;&gt;&gt; f.flush()

abc

12.2.6 seek()從指定位置讀取

&gt;&gt;&gt; f.tell()

&gt;&gt;&gt; f.seek(9)

9

&gt;&gt;&gt; f.seek(5,1)  # 1表示從目前位置開始

14

12.2.7 tell()傳回目前指針位置

&gt;&gt;&gt; f.tell()   

16

&gt;&gt;&gt; f.close()  # 使用完後關閉檔案

<b>12.3 檔案對象增删改查</b>

在shell中,我們要想對檔案指定行插入内容、替換等情況,使用sed工具很容易就實作。在本章節講的open()函數并沒有直接類似與sed工具的方法,要想實作這樣的操作,變通的處理能到達此效果,主要思路是先讀取内容修改,再寫會檔案,以下舉幾個常用的情況 。

12.3.1 在第一行增加一行

例如:在開頭添加一個test字元串

#!/usr/bin/python

# -*- coding: utf-8 -*-

f = open('test.txt', 'r')

data = f.read()

data = "test\n" + data

f = open('test.txt', 'w')

f.write(data)

f.flush()

# python test.py

test

先将資料讀出來,然後把要添加的test字元串拼接到原有的資料,然後在寫入這個檔案。

12.3.2 在指定行添加一行

例如:在第二行添加一個test字元串

data_list = f.readlines()  # 經測試,此方法比下面疊代效率高

# data_list = []

# for line in f:

#     data_list.append(line)

data_list.insert(1, 'test\n')

# data = ''.join(data)

# f.write(data)

f.writelines(data_list)  

f.close

先将資料以清單存儲,就可以根據下标插入到指定位置,也就是哪一行了。再通過join把清單拼接成字元串,最後寫到檔案。

12.3.3 在比對行前一行或後一行添加test字元串

data_list = f.readlines()

data_list.insert(2-1, 'test\n')  # 在指定行減去一行就是上一行了,下一行插入同理

f.writelines(data_list)

12.3.4 删除指定行

例如:删除第三行,與在指定行添加同理

data_list.pop(2)

例如:隻保留第一行至第三行

data_list = f.readlines()[0:2]  # 清單切片

f.write(data_list)

12.3.5 删除比對行

例如:删除比對py字元的行

data = f.readlines()

# for line in data:

#     if line.find('py') == -1:   # 如果目前行不包含py字元,會傳回-1,否則傳回下标

#         data_list.append(line)

data_list = [line for line in data if line.find('py') == -1]  

12.3.6 全局替換字元串

data.replace('old string', 'new string')

12.3.7 在指定行替換字元串

例如:将c++改為c#

data_list = []

for line in data:

    if data.index(line) == 2:

        data_list.append(line.replace('++', '#'))

    else:

        data_list.append(line)

12.3.8 處理大檔案

在讀取上g檔案時,直接讀取所有内容會導緻記憶體占用過多,記憶體爆掉。要想提高處理效率,有以下兩種方法:

方法1:open()打開檔案傳回的對象本身就是可疊代的,利用for循環疊代可提高處理性能

&gt;&gt;&gt; f = open('test.txt')

&gt;&gt;&gt; for line in f:

...   print line   # 每行後面會有一個換行符\n,是以會列印出來換行符,可以使用line.strip('\n')去除

...

方法2:每次隻讀取固定位元組

f = open('test.txt')

while true:

    data = f.read(1024)  # 每次隻讀取1024位元組

    if not data: break

12.3.9 下載下傳檔案

方法1:

import urllib

url = "http://nginx.org/download/nginx-1.10.1.tar.gz"

urllib.urlretrieve(url, "nginx-1.10.1.tar.gz")

方法2:

import urllib2

f = urllib2.urlopen(url).read()

with open("nginx-1.10.1.tar.gz", "wb") as data:

    data.write(f)

<b>12.4 fileinput</b>

fileinput子產品是python内模組化塊,用于周遊檔案,可對多檔案操作。

fileinput.input([files[, inplace[, backup[, mode[, openhook]]]]])

files:檔案路徑,多檔案這樣寫['1.txt,'2.txt'']

inplace:是否将标準輸出寫到原檔案,預設是0,不寫

backup:備份檔案擴充名,比如.bak

mode:讀寫模式,預設r,隻讀

openhook:

fileinput.isfirstline()

檢查目前行是否是檔案的第一行

fileinput.lineno()

傳回目前已經讀取行的數量

fileinput.fileno()

傳回目前檔案數量

fileinput.filelineno()

傳回目前讀取行的行号

fileinput.filename()

傳回目前檔案名

12.4.1 周遊檔案内容

import fileinput

for line in fileinput.input('test.txt'):

    print line

# python test.py 

12.4.2 傳回目前讀取行的行号

    print fileinput.filelineno()

    print line,  # 逗号忽略換行符

1

2

3

4

12.4.3 全局替換字元,修改原檔案

for line in fileinput.input('test.txt', backup='.bak', inplace=1):

    line = line.replace('++','#')

    print line,

先把要操作的檔案備份一個以.bak的字尾檔案,inplace=1是将标準輸出寫到原檔案,也就是這個腳本如果沒有标準輸出,就會以空資料寫到原檔案。

12.4.4 對多檔案操作

for line in fileinput.input(['test.txt', 'test2.txt']):

12.4.5 實時讀取檔案新增内容,類似tail -f

with open('access.log') as f:

     f.seek(0,2)   # 每次打開檔案都将檔案指針移動到末尾

     while true:  

         line = f.readline()

         if line:

             print line,

這個死循環會一直執行下面的操作。很消耗性能。

我們可以加個休眠,每秒讀取一次:

import time

     f.seek(0,2)

     while true:

         line = f.readline()

         if line:

         else:

             time.sleep(1)

<b>12.5 shutil</b>

shutil子產品是python内模組化塊,用于檔案或目錄拷貝,歸檔。

shutil.copyfile(src, dst)

複制檔案

shutil.copytree(src, dst)

複制檔案或目錄

shutil.move(src, dst)

移動檔案或目錄

shutil.rmtree(path,ignore_errors=false, onerror=none)

遞歸删除目錄。os.rmdir()不能删除有檔案的目錄,就可以用這個了

shutil.make_archive(base_name, format, root_dir=none, base_dir=none, verbose=0, dry_run=0, owner=none, group=none, logger=none)

python2.7以後才有這個方法。

功能是建立zip或tar歸檔檔案。

base_name:要建立歸檔檔案名

format:歸檔檔案格式,有zip、tar、bztar、gztar

root_dir:要壓縮的目錄

base_dir:?

用法:shutil.make_archive('wp','zip','/root/wordpress')   

<b>12.6 with語句</b>

在處理一些事務時,可能會出現異常和後續的清理工作,比如讀取失敗,關閉檔案等。這就用到了異常處理語句try...except,如下:

try:

    data = f.read()

finally:

    f.close()

python對于這種情況提供了一種更簡單的處理方式,with語句。處理一個檔案時,先擷取一個檔案句柄,再從檔案中讀取資料,最後關閉檔案句柄。如下:

with open('test.txt') as f:

可見這種方式顯得更簡約,一些異常、清理工作都交給with處理了。