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
二進制模式寫,清空檔案内容
例如:打開一個檔案
>>> f = open('test.txt', 'r')
>>> 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()讀取所有内容
>>> f.read()
'1.python\n2.java\n3.c++\n4.ruby\n'
# 擷取指定位元組
指定讀取多少位元組:
>>> f.read(9)
'1.python\n'
12.2.2 readline()讀取下一行内容
>>> f.readline()
'2.java\n'
12.2.3 readlines()讀取所有内容傳回一個清單
>>> f.readlines()
['1.python\n', '2.java\n', '3.c++\n', '4.ruby\n']
12.2.4 wirte()寫入字元串到檔案
>>> f = open('test.txt', 'a') # 以追加方式打開檔案
>>> f.write("5.shell\n") # 這一步并沒有真正寫到檔案
>>> f.flush() # 重新整理到磁盤才寫到檔案
5.shell
12.2.5 wirtelines()寫入一個序列字元串到檔案
>>> f = open('test.txt', 'a')
>>> f.writelines(['a','b','c'])
>>> f.flush()
abc
12.2.6 seek()從指定位置讀取
>>> f.tell()
>>> f.seek(9)
9
>>> f.seek(5,1) # 1表示從目前位置開始
14
12.2.7 tell()傳回目前指針位置
>>> f.tell()
16
>>> 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循環疊代可提高處理性能
>>> f = open('test.txt')
>>> 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處理了。