1. 程式人生 > >Python 檔案讀寫

Python 檔案讀寫

一.file物件(file-like Object)

在標準庫中,不需要安裝

1.file 物件使用 open 函式來建立: f = open(/path/1.txt, mode='r')

2.open函式引數: open(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True)

  • file:必需,檔案路徑(相對或者絕對路徑);
  • mode: 檔案開啟模式;
  • buffering:可取值有0,1, >1三個,0代表buffer關閉(只適用於二進位制模式),1代表line buffer(只適用於文字模式),>1表示初始化的buffer大小;
  • encoding:表示的是返回的資料採用何種編碼,一般採用utf8或者gbk;
  • errors的取值一般有strict,ignore,當取strict的時候,字元編碼出現問題的時候,會報錯,當取ignore的時候,編碼出現問題,程式會忽略而過,繼續執行下面的程式。
  • newline:可以取的值有None, \n, \r, ’’, ‘\r\n’ ,用於區分換行符,但是這個引數只對文字模式有效;
  • closefd:取值與傳入的檔案引數有關,預設情況下為True,傳入的file引數為檔案的檔名,取值為False的時候,file只能是檔案描述符,什麼是檔案描述符,就是一個非負整數,在Unix核心的系統中,開啟一個檔案,便會返回一個檔案描述符。

3.常見mode模式:

  • r或rt:預設模式,文字模式讀
  • rb:二進位制檔案
  • w或wt:文字模式寫,開啟前檔案儲存被清空
  • wb:二進位制寫,檔案儲存同樣被清空
  • a:追加模式,只能寫在檔案末尾
  • a+:可讀寫模式,寫只能寫在檔案末尾
  • w+:可讀寫,與a+的區別是要清空檔案內容
  • r+:可讀寫,與a+的區別是可以寫到檔案任何位置

4.file物件函式:

  • file.close():關閉檔案。關閉後文件不能再進行讀寫操作。
  • file.next():返回檔案下一行。
  • file.read([size]):從檔案讀取指定的位元組數,如果未給定或為負則讀取所有。
  • file.readline([size]):讀取整行,包括 “\n” 字元。
  • file.readlines([sizeint]):讀取所有行並返回列表,若給定sizeint>0,則是設定一次讀多少位元組,這是為了減輕讀取壓力。
  • file.seek(offset[, whence]):設定檔案當前位置。
  • file.tell():返回檔案當前位置。
  • file.truncate([size]):擷取檔案,擷取的位元組通過size指定,預設為當前檔案位置。
  • file.write(str):將字串寫入檔案,返回的是寫入的字元長度。
  • file.writelines(sequence):向檔案寫入一個序列字串列表,如果需要換行則要自己加入每行的換行符。

5.with語句: 檔案讀寫完畢後必須呼叫f.close()的原因:

  • 檔案使用完畢後必須關閉,因為檔案物件會佔用作業系統的資源,並且作業系統同一時間能開啟的檔案數量也是有限的;
  • 寫檔案時,作業系統往往不會立刻把資料寫入磁碟,而是放到記憶體快取起來,空閒的時候再慢慢寫入。只有呼叫close()方法時,作業系統才保證把沒有寫入的資料全部寫入磁碟。忘記呼叫close()的後果是資料可能只寫了一部分到磁碟,剩下的丟失了。

可以使用 try … finally 來實現,但是每次都這麼寫實在太繁瑣:

try:
    f = open('/path/to/file', 'r')
    print(f.read())
finally:
    if f:
        f.close()

try:
    f = open('/Users/michael/test.txt', 'w')
    f.write('Hello, world!')
finally:
    if f:
        f.close()

Python引入了with語句來自動幫我們呼叫close()方法:

with open('/path/to/file', 'r') as f:
    print(f.read())
    
with open('/Users/michael/test.txt', 'w') as f:
    f.write('Hello, world!')

這和前面的try … finally是一樣的,但是程式碼更佳簡潔,並且不必呼叫f.close()方法。

二.CSV模組

在標準庫中,不需要安裝

1.reader函式: reader(csvfile, dialect='excel', **fmtparams)

引數說明:

  • csvfile:必須是支援迭代(Iterator)的物件,可以是檔案(file)物件或者列表(list)物件,如果是檔案物件,開啟時需要加"b"標誌引數。
  • dialect:編碼風格,預設為excel的風格,也就是用逗號(,)分隔,dialect方式也支援自定義,通過呼叫register_dialect方法來註冊,下文會提到。
  • fmtparam:格式化引數,用來覆蓋之前dialect物件指定的編碼風格。

函式:

  • csvreader.__next__(): Return the next row of the reader’s iterable object as a list (if the object was returned from reader()) or a dict (if it is a DictReader instance), parsed according to the current dialect. Usually you should call this as next(reader).

屬性:

  • csvreader.dialect: A read-only description of the dialect in use by the parser.
  • csvreader.line_num: The number of lines read from the source iterator. This is not the same as the number of records returned, as records can span multiple lines.

2.writer函式: writer(csvfile, dialect='excel', **fmtparams)

函式:

  • csvwriter.writerow(row): Write the row parameter to the writer’s file object, formatted according to the current dialect.
  • csvwriter.writerows(rows): Write all elements in rows (an iterable of row objects as described above) to the writer’s file object, formatted according to the current dialect.

屬性:

  • csvwriter.dialect: A read-only description of the dialect in use by the writer.

3.register_dialect函式: 自定義dialect register_dialect(name, [dialect, ]**fmtparams)

  • name:你所自定義的dialect的名字,比如預設的是’excel’,你可以定義成’mydialect’。
  • [dialect, ]**fmtparams:dialect格式引數,有delimiter(分隔符,預設的就是逗號)、quotechar、quoting等等,可以參考官方文件。

4.unregister_dialect函式: 登出自定義的dialect unregister_dialect(name)

5.常用語句:

  • 從檔案中獲取列標題:
import csv

filename = '1.csv'
with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)

    for index, column_header in enumerate(header_row):
        print(index, column_header)
  • 從檔案中獲取某一列:
import csv

filename = '1.csv'
with open(filename) as f:
    reader = csv.reader(f)
    next(reader)

    highs = []
    for row in reader:
        highs.append(row[4])

    print(highs)

三.DOCX模組

不在標準庫中,需要安裝(通過命令列下載的docx安裝包未完全相容python3,需要另行下載): 在 https://www.lfd.uci.edu/~gohlke/pythonlibs/ 中找到python_docx-x.x.x-py2.py3-none-any.whl 下載到本地後安裝:pip install python_docx-x.x.x-py2.py3-none-any.whl

1.檔案讀取與寫入:

import docx

doc = docx.Document('1.docx')
# doc = docx.Document()  僅新建一個Document物件,不讀取檔案
doc.save('2.docx')

2.表格:

寫入表格

import docx

doc = docx.Document()

# 建一個4行3列的表
table = doc.add_table(rows=1, cols=3, style='Table Grid')

header_cells = table.rows[0].cells
header_cells[0].text = 'Name'
header_cells[1].text = 'Id'
header_cells[2].text = 'Desc'

data_lines = 3
for i in range(data_lines):
    cells = table.add_row().cells
    cells[0].text = "Name%d" %i
    cells[1].text = "Id%d" %i
    cells[2].text = "Desc%d" %i

# 建一個2行4列的表
rows = 2
cols = 4
table = doc.add_table(rows=rows, cols=cols)

val = 1
for i in range(rows):
    cells = table.rows[i].cells
    for j in range(cols):
        cells[j].text = str(val * 10)
        val += 1

doc.save('tmp.docx')

讀取表格

import docx

doc = docx.Document('tmp.docx')
for table in doc.tables:  # 遍歷所有表格
    print('----table------')
    for row in table.rows:  # 遍歷表格的所有行
        # 方法一
        for cell in row.cells:
            print(cell.text + '\t', end='')
        print()
        # 方法二
        row_str = '\t'.join([cell.text for cell in row.cells])
        # ''.join()插入分隔符
        print(row_str)

3.段落:

import docx

doc = docx.Document('1.docx')
content = '\n'.join([para.text for para in doc.paragraphs])
print(content)

4.綜合運用:

from docx import Document
from docx.shared import Inches

document = Document()

document.add_heading('Document Title', 0)

p = document.add_paragraph('A plain paragraph having some ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True

document.add_heading('Heading, level 1', level=1)
document.add_paragraph('Intense quote', style='Intense Quote')

document.add_paragraph(
    'first item in unordered list', style='List Bullet'
)
document.add_paragraph(
    'first item in ordered list', style='List Number'
)

document.add_picture('1.png', width=Inches(1.25))

records = (
    (3, '101', 'Spam'),
    (7, '422', 'Eggs'),
    (4, '631', 'Spam, spam, eggs, and spam')
)

table = document.add_table(rows=1, cols=3)
hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Qty'
hdr_cells[1].text = 'Id'
hdr_cells[2].text = 'Desc'
for qty, id, desc in records:
    row_cells = table.add_row().cells
    row_cells[0].text = str(qty)
    row_cells[1].text = id
    row_cells[2].text = desc

document.add_page_break()

document.save('demo.docx')

效果