presenter: 賴昱錡

Python

例外處理 & 檔案讀寫/管理

Index

文字檔案處理

開啟/關閉檔案

f = open('檔名', 模式)
# 開啟檔案
f.close()
# 關閉檔案
  • 檔名: 要讀寫的檔案名稱 (字串型態、不可省略
  • 模式: 開啟檔案的模式,通常由 r,w,a 控制 (預設是 r )

讀寫模式

字元 說明
r 唯讀。檔案必須存在
r+ 讀寫。檔案必須存在,寫入會覆蓋原本內容。
w 只寫。文件內容清零。
w+ 讀寫。文件內容清零。
a 只寫。新增在檔案後面
a+ 讀寫。新增在檔案後面

*b: 二進位模式

讀檔

f = open('檔名', '模式')
# 開啟檔案
print(f.read())
# 印出所有內容
print(f.read(7))
# 印出前 7 個字元
print(f.readline())
# "依序"印出檔案中每一行
f.close()
  • 其實還有 iter,以及透過 linecache 模組中 getline (讀取特定行) 等方式
  • 比較不常用
for index, items in enumerate(f.readlines()):
  print(f'No.{index}: {items}')

# readlines 回傳由各行字串組成的"陣列"
# enumerate 可以枚舉陣列的索引&內容

寫檔

f = open('test.txt', 'a')
f.write('\nHello world!')
people = ['\nBrineTW', '\nO.O', '\nAaronWu', '\nHakui Koyori']
f.writelines(people)

print(people, file = f)

f.close()
  • write(): 正常地寫入 (依照讀檔模式)
  • writelines(): 把陣列內容寫入檔案
  • print(): 指定目標、內容,用途類似

with open() as ..

path = 'text.txt'
with open(path, 'w') as f:
    for line in f.readlines():
        print(line)
  • f.close() 好麻煩 @@
  • 這個方法可以自動呼叫 f.close()

鬧鬼了

# python 檔案
f = open('test.txt', 'r')
for i in f.readlines():
    print(i)
for i in f.readlines():
    print(i)
  • 怎麼只輸出一次內容 > <
  • file object 在處理檔案時會將光標移至最後的位置,不會自動移回來
#test.txt
1 2 3
4 5 6
7 8 9

移動位置

f = open('test.txt', 'r')
for i in f.readlines():
    print(i)
print(f.tell())
f.seek(0)
for i in f.readlines():
    print(i)
  • f.seek(n): 把指針移至第 n 個字元
  • f.tell(): 印出指針的位置
  • f.next(): 將檔案指標移到下一行

其他

f = open('test.txt', 'r+')
f.seek(0)
f.flush()
print(f.readable())
print(f.writable())
  • f.flush():  把緩衝內容寫入檔案、清除緩衝區資料
  • f.writable():  檔案是否可寫
  • f.readable():  檔案是否可讀
  • 要怎麼讀取 .csv 、.json 等格式的檔案?
  • 運用 python 的 csv、json 模組!
  • open 只有兩個參數?
  • 除了檔名、模式,也可以選擇編碼模式 (encoding)!
  • 沒有 close 會?
  • 占用不少系統的資源!

問題

檔案管理

os 等模組運用

os.path

import os.path
  • os 是一種與作業系統相關的模組,提供數十種與作業系統溝通的函式,常用於檔案的複製、修改、查詢等,使用頻率相當高。
  • os.path 套件提供相關函式,用以處理檔案路徑與名稱資訊,必須先引入。

路徑相關

import os.path
f = open("file.txt", "a+")
seek(0)

print(os.path.abspath('test.txt')) # 取得檔案絕對路徑
print(os.path.relpath('test.txt')) # 取得鄉對路徑

系統相關

import os.path

print(os.system("notepad.exe")) #開啟記事本
print(os.system("calc.exe")) #開啟計算機

print(os.name) # 取得當前的使用平臺
# Windows用'nt'表示,Linux用'posix'表示
print(os.getcwd()) # 取得當前的工作目錄

資料夾相關

import os

# 創建資料夾
os.mkdir('./os_practice')
os.mkdir('./testdir')

# 刪除資料夾
os.rmdir('./testdir')

# 列出資料夾中所有檔案
os.listdir('os_practice')

其他

import os
# 查看當前路徑是否存在...
print(os.path.exists('1.txt'))
# 查看當前項目是否為檔案
print(os.path.isfile('abcd'))
# 更改檔名
os.rename('./json/poem3.txt', 'poem3.txt')
# 移除檔案
os.remove('orz.cpp')

shutil

import shutil
# 複製檔案,前面為來源,後面為目的地
shutil.copy('1.txt', '2.txt')
# 移動檔案並更名
shutil.move('1.txt', abc)

錯誤與例外處理

在撰寫 Python 程式時,若過程出現 bug,系統會回傳 Error Message,該如何解讀其實是件蠻重要的事!

錯誤訊息

  1. if-else statement 、 for loop 、 函式宣告的 def 等等沒有加冒號
  2. 在判斷式當中,將 == 寫成 =
  3. 字串前後並未完整加上引號
  4. 更多的手殘打錯

Syntax Error

所謂的 NameError 是指當電腦無法找到我們所指定的變數時產生的錯誤,通常發生在打錯變數名稱,或是使用了並未宣告過的變數的時候。

NameError

通常出現在當我們誤用了變數的資料型態的時候,比如說對著整數變數跑 for i in 變數 、試圖改變 string 字串的特定字元、對著兩個不同資料型態( int 與 float 之間除外)使用 >、<、== 等等判斷用的運算子。

TypeError

ZeroDivisionError 指的是我們在進行運算時,拿 0 當成除數時所產生的錯誤。

ZeroDivisionError

這個錯誤來自於使用了錯誤的 index ,也就是可能使用到了可用範圍之外的 index。KeyError 與這種錯誤類似,但比較常出現在字典的使用上。 

IndexError

Try...Except?

例外處理

try:
  #嘗試執行的程式碼
except 例外名稱:
  #當遇到例外時要執行的程式碼

我們先嘗試執行 try 底下的程式碼,如果無法順利執行,在過程中產生了例外,就會接著執行 except 下的程式碼

更詳細的運用~

應用

try:
  #嘗試執行的程式碼
except 例外名稱:
  #當遇到特定的例外時要執行的程式碼
except:
  #當未指定的例外發生時要執行的程式碼
else:
  #若 try 當中的程式碼並未產生例外時要執行的區塊
finally:
  #無論如何都要執行的程式碼

這樣寫有什麼好處?

Example:

try:
    a = int(input())
    b = int(input())
    c = a/b
except ZeroDivisionError:
    print("Cannot divide by 0!")
except TypeError:
    print("Wrong input")
except:
  	print("未知的錯誤")
else:
    print("The answer is " + str(c))
finally:
    print("Program finished")

作業

1. 請實作一個簡單的程式,可以將當前路徑所有 .jpg 為副檔名的檔案 (包含其子目錄的,且保證路徑裡的資料夾最多只會有一層),移動到 /data 資料夾 (若不存在則建立一個) 中。

2. 簡單用 50~100 字介紹 .csv、.json檔案的特色,並附上處理該類型檔案程式碼作為解說。

 

若有興趣,可以把作業內容繳交至 expectlai@outlook.com :) 

作業

Thank You!

參考資料

Made with Slides.com