---
# System prepended metadata

title: wk15_1214_CH9檔案與例外處理
tags: [python]

---

{%hackmd @themes/orangeheart %}
## wk15_1214_CH9檔案與例外處理 
### 醫放三 B1003210 應雨岑
1. 檔案的操作
    - 開啟檔案的語法
    - 開啟檔案的模式
    - 使用with...as 語法
    - 檔案處理
2. 檔案和目錄管理
    - os.path 模組
    - os 模組
3. 例外處理
    - try...except...else...finally 語法
    - try...except...else...finally 使用方法
    - try...except 常用錯誤表
4. LINE 貼圖抓取方式
5. 凱薩密碼的專案介紹
## 今日課程內容
<pre>
1. 抓取LINE 貼圖的圖片檔
2. 介紹凱薩密碼
</pre>
## NOTE
<pre>
# 建立資料夾的方式
images_dir= "line_image3/"         
if not os.path.exists(images_dir):
    os.mkdir(images_dir)
#以程式進行複製東西
shutil.copyfile(source_path, destination_path)

例外處理--finally是在 try…except完成之後都會執行的動作
  open --mode是設定檔案開啟的模式，他也是字串的型態，當沒有特別指定模式什麼時就會以讀取模式當作預設
檔案處理--readable是測試可不可以讀取；read可以指定讀取長度若沒有指定則讀所有；readlines則是讀取所有內容而傳回一個串列
開啟檔案--w是指寫入檔案，當指定檔案不存在時會新增，有則會覆蓋內容
</pre>
## [ INCLASS PRACTICE ]

```python
## chatGpt  local jpg
import shutil

source_path = r'C:\zzz\111.png'
destination_path = r'C:\zzz\1.png'

# 複製文件
shutil.copyfile(source_path, destination_path)

print(f'已從 {source_path} 複製到 {destination_path}')
```


```python
## chatGpt line png

import requests
import os

url = 'https://stickershop.line-scdn.net/stickershop/v1/sticker/230054638/android/sticker.png?v=1'
save_path = r'C:\zzz\3.jpg'

#response = requests.get(url, stream=True)
response = requests.get(url)

with open(save_path, 'wb') as file:
    for chunk in response.iter_content(chunk_size=8192):
        file.write(chunk)

print(f'已從 {url} 下載並保存到 {save_path}')
```


```python
## 課本原始檔--可下載表情貼圖片到"下載(和python同個資料夾)"內

import requests, json, os
from bs4 import BeautifulSoup
url = 'https://store.line.me/emojishop/product/62342308a5292a1f330d948a/zh-Hant' #mini rabbit
html = requests.get(url)

sp = BeautifulSoup(html.text, 'html.parser')

#datas = sp.find_all('li', {'class':'mdCMN09Li FnStickerPreviewItem'})
datas = sp.find_all('li', {'class':'mdCMN09Li FnStickerPreviewItem'})

# 建立目錄儲存圖片


for data in datas:
    imginfo = json.loads(data.get('data-preview'))
    id = imginfo['id']
    imgfile = requests.get(imginfo['animationUrl'])
    full_path = images_dir + id + '.png'
    
    with open(full_path, 'wb') as f:    #寫入資料
        f.write(imgfile.content)
        print(full_path) 
```

    line_image3/001.gif
    line_image3/002.gif
    line_image3/003.gif
    line_image3/004.gif
    line_image3/005.gif
    line_image3/006.gif
    line_image3/007.gif
    line_image3/008.gif
    line_image3/009.gif
    line_image3/010.gif
    line_image3/011.gif
    line_image3/012.gif
    line_image3/013.gif
    line_image3/014.gif
    line_image3/015.gif
    line_image3/016.gif
    line_image3/017.gif
    line_image3/018.gif
    line_image3/019.gif
    line_image3/020.gif
    line_image3/021.gif
    line_image3/022.gif
    line_image3/023.gif
    line_image3/024.gif
    line_image3/025.gif
    line_image3/026.gif
    line_image3/027.gif
    line_image3/028.gif
    line_image3/029.gif
    line_image3/030.gif
    line_image3/031.gif
    line_image3/032.gif
    line_image3/033.gif
    line_image3/034.gif
    line_image3/035.gif
    line_image3/036.gif
    line_image3/037.gif
    line_image3/038.gif
    line_image3/039.gif
    line_image3/040.gif
    


```python
import string
import matplotlib.pyplot as plt

LETTERS = 'abcdefghijklmnopqrstuvwxyz,.()1234567890 '

def encrypt(initial, shift):
  initial = initial.lower()
  output = ""

  for char in initial:
    if char in LETTERS:
      output += LETTERS[(LETTERS.index(char) + shift) % len(LETTERS)]

  return output

def decrypt(initial, shift):
  initial = initial.lower()
  output = ""

  for char in initial:
    if char in LETTERS:
      output += LETTERS[(LETTERS.index(char) - shift) % len(LETTERS)]
      
  return output

def plot_letter_frequency(text):     #通常
    text = text.lower()
    letter_count = {letter: 0 for letter in string.ascii_lowercase}

    for char in text:
        if char.isalpha():
            letter_count[char] += 1

    letters = list(letter_count.keys())
    counts = list(letter_count.values())

    plt.bar(letters, counts)
    plt.xlabel('Letters')
    plt.ylabel('Frequency')
    plt.title('Letter Frequency in Text')
    plt.savefig('./result.png')

## ---------------  Main  ------------------
message = input('請輸入要加密的訊息: ')
key = int(input('請輸入密鑰: '))

# 加密
cipher = encrypt(message, key)
print(f'\n加密結果: {cipher}')

# 解密
plain = decrypt(cipher, key)
print(f'\n解密結果: {plain}')

#字數統計
plot_letter_frequency(cipher)
```

    請輸入要加密的訊息: my name is Kelly123456789
    請輸入密鑰: 26
    
    加密結果: 9jz0,91z5dz7188jpqrstuvwx
    
    解密結果: my name is kelly123456789   
![result](https://hackmd.io/_uploads/B1axElc8a.png =70%x)

    


## 全部的note
<pre>

W1
計算符號之間可以加空白鍵 <br>
** : 幾次方<br>
sep="." : 分隔符號為.
end="/" : 結束用/結束

在print內寫入%d : 放入參數答案  (最後在答案要加%)
            %s : 放入的答案為字串
            %f : 放入的答案包含全部小數點
            %.1f :        包含 1位小數點
            %.3f :        包含 3位小數點
寫法如下- print("身高為%d cm，體重為%d kg，BMI為%.1f " % (height,weight,bmi))
                  
print("顯示的文字",參數名字)<br>
my_height = input("請輸入身高(cm)") : 可以輸入文字進去對話框
使用者輸入的文字要轉換成"int"  ()<br>

W2
print("姓名  成績")
print("%3s %3d"%(name1,score1))   #按照字元數進行規則排列出一格表格格式

W3
**次方
//整除的數
/除以
%餘數
and 放在兩個運算子中間，判斷True or False，當兩個都為True才會是True
or 放在兩個運算子中間，判斷True or False，當兩個都為False才會是False

W4
if,else,elif需使用冒號:還有縮排來寫code
.upper可以讓程式不用判斷大小寫

W5
串列list用中括弧括起來
for和其他語法一樣，他同樣也是需要用到:還有縮排來寫程式

W6
break會跳出這個迴圈
continue跳出執行這個code 繼續執行下一個i的程式
None 為一個什麼都沒有的數字，但是他可以做加減乘除的運算

W7
串列名稱=[1,2,3,...]  #可以放字串、數字等等的
另外也可以宣告空的串列list=[]
多為變數的宣告
    list=[["1"],["1,2"],["1,2,3"]]
    如果想要顯示第二個串列的第一個內容:print(list[1][0]))    
    # 0表示第一個資料，1表示第二個-意思是程式計算的方式是由0開始數
若想檢索特定的元素可以使用list[起始索引,終止索引,間隔]的方式進行
也可以索引-值，表示從最後一個開始數list[-1]
len(list)可以計算元素數量
max(list)可以找到元素內最大值
list.index(...)可以找...在清單中第幾個
    .count     可以數...出現幾次
    .append    插入一個元素在最後
    .insert(3,8)插入8某一個位置(第三個)
    .pop       移除最後一個元素

W8
divmod(7,3)   #答案為(2,1) 表示(商,餘數)
元組內的元素不能修改，但可以轉換成串列
字典是以大括號呈現{}
由小排到大 score.sort()
由大排到小 score.sort(reverse=True)
反轉是錯誤的則不用反轉，由小排到大 score.sort(reverse=False)

W9
字典語法 dict_血型個性={"A":"穩重","B":"樂觀","O":"堅強","AB":"自然"}

W10
下載code的md檔案--用於期末的hackMd筆記
自訂一個函式  def sayhello():
呼叫這個sayhello程式  sayhello()    
沒有設預設值  def sayhello2(name):                #不會出現東西，因為沒有寫預設是什麼
有設定預設值  def sayhello2(name= "my friend"):   #沒有特別寫name是什麼，就會使用預設值
如果有一個參數有設預設值另一個沒設，則有設預設值的函數就要放在靠後面
在函式def內設的參數var1=1都是區域變數，如果跳出這個函式後就不存在這個設定，因此如要變成全域函數要用 global var1 \n var1=1

W11
函式模組重點: def,return
只要模組裡面有程式區塊就需要使用return
把time的模組匯成t  --> import time as t 
匯入time裡面的其他模組，因此在使用時就不需要寫成time.sleep而可直接寫sleep  -->from time import sleep,ctime
在python中安裝程式的方法(安裝numpy)   --> ! pip install numpy

W12
join 函式可將串列中元素連接組成一個字串
r.sample("123456789",4)    #1-9數字當中隨機選4個數字
while True:     #對就會一直執行

W13
認識演算法--解決問題的方法
泡沫排序--為一個個比較大小而放入對應的位置
url=requests.get("https://zh.wikipedia.org/wiki/Special:Random")  #打開隨機的WIKI網頁

W14
搜尋主要可以分為循序搜尋以及二分搜尋法
    - 循序搜尋: 是從第0個元素開始檢查比對，當有成功比對到才會結束，若無，就會比到最後一個
    - 二分搜尋: 是先將串列資料排序好在以中央串列元素將串列分成2半，再去比較必較大還是比較小
with open(f"./{}.md,'w'}  創建一個檔案
</pre>

## [ afterclass practice ]

>　1. 綜合演練 選擇題1-10  (需抄題在markdown cell ; 有程式碼的題目要有code cell )
> 2. 教學影音 lesson 9
> 3. 請填寫小組報告主題  --- 【期末小組】管理  ---國考題爬蟲
> 4. 請填寫筆記網站網址  --- 【OMP】問卷      ---[https://hackmd.io/@B1003210/ByXp26FQa](https://hackmd.io/@B1003210/ByXp26FQa)

* ## 1. 綜合演練 選擇題1-10

### ( A ) 1. 以open(filename[,mode][,encode]) 開啟檔案，下列何者是 mode 參數預設的模式?

(A) 讀取模式 (B) 寫入模式 (C) 附加模式 (D)以上皆是

#### 因為mode是設定檔案開啟的模式，他也是字串的型態，當沒有特別指定模式什麼時就會以讀取模式當作預設

### ( C ) 2. Python 提供何種內建函式，可以開啟指定的檔案，以便進行檔案內容的讀取、寫入或修改？

(A) file() (B) input() (C) open() (D) output()

#### 因為open(filename[,mode][,encode])

### ( B ) 3. 下列何函式可以讀取一列字元？

(A) readable() (B) read() (C) readlines() (D)get(ch)

#### 因為readable是測試可不可以讀取；read可以指定讀取長度若沒有指定則讀所有；readlines則是讀取所有內容而傳回一個串列


```python
f=open('test.txt','r',encoding='utf-8')
check=f.readable()
print(check)

read=f.read(5)
print(read)

readlines=f.readlines()
print(readlines)

f.close
```

    True
    哈哈哈哈囉
    ['!!!!!\n', '\n', '123456789']
    




    <function TextIOWrapper.close()>



### ( B ) 4. 下列程式建立的檔案物件，可以執行何種動作？
<pre>
f=open('file1.txt','w')
f.write("Hello Python!")
f.close()
</pre>
(A) 讀取 (B) 寫入 (C) 可讀取也可寫入 (D) 以上皆非

#### 因為w是指寫入檔案，當指定檔案不存在時會新增，有則會覆蓋內容


```python
with open('test.txt','w') as f:
    f.write("Hello Python!")
f=open('test.txt','r',encoding='utf-8')
read=f.read()
print(read)
f.close
```

    Hello Python!
    




    <function TextIOWrapper.close()>



### ( D ) 5. 執行下列程式，下列顯示結果何者正確？
<pre>
try:
    print(x)
except:
    print("y")
finally:
    print("z")

(A) x (B) y (C) xz (D) yz
</pre>
#### 因為沒有設定x是什麼，因此會跳到except去而印y，最後印出z因為finally是一定會執行的


```python
try:
    print(x)
except:
    print("y")
finally:
    print("z")
```

    y
    z
    

### ( A ) 6. open(filename,mode,encode) 函式的參數中，其中只有那一個參數是必填？

(A) filename (B) mode (C) encode (D) 以上皆是

#### 因為其他如果沒有填會用預設值，但filename一定要告訴程式

### ( B ) 7. 如果作業系統是繁體中文 Windows 系統，預設的編碼為何？

(A) UTF-8 (B) cp950 (C) unicode (D) GB2312

#### 因為在中文 Windows 系統預設的編碼通常是「Big5」，他主要是一種用來表示繁體中文字的編碼方式(包含了繁體字中的國字、注音符號、標點符號...)，也就是說Big5 編碼通常被用來處理繁體中文的顯示和輸入，不過現在的Windows 系統也支援其他編碼像是UTF-8

### ( D ) 8. 下列有關 readlines() 的敘述，何者正確？

(A) 會讀取全部文件內容 (B) 以串列方式傳回

(C) 包括「\n」跳列字元，甚至是隱含的字元 (D) 以上皆是

#### 因為他會讀取所有內容而傳回一個串列，如下所示


```python
with open('test.txt','r') as f:
    readlines=f.readlines()
    print(readlines)
```

    ['Hello Python!']
    

### ( A ) 9. 執行下列程式，下列顯示結果何者正確？
<pre>
n=1
try:
    print(n)
except:
    print("變數不存在!")
</pre>
(A) 1 (B) n (C) 變數不存在 (D) 以上皆是

#### 因為n存在就不會執行到except，而是直接印出n


```python
n=1
try:
    print(n)
except:
    print("變數不存在!")
```

    1
    

### ( C ) 10. 班上的除錯高手大匹，在他的程式中加入了錯誤的補捉在 try…except…finally 敘述中，無論例外有沒有發生都會執行下列那些程式區塊？

(A) try (B) except (C) finally (D) 以上皆是

#### 因為finally是在 try…except完成之後都會執行的動作


```python
try:
    print(x)
except:
    print("現在在執行except")
finally:
    print("我一定會出現!!!")
```

    現在在執行except
    我一定會出現!!!
    

* ## 2. 教學影音 lesson 9、10

1. 新手練習9-模組 
<pre>函式的設定只能用在原本用的那個區塊(檔案)中，
如果要在其他地方使用這個函是即須宣告函式import area，
也可以重新命名函式的名稱import my_module as a再輸入a.area()，
另外也可以只匯入其中一個函式from my_module import area
</pre>
2. 新手練習10-class類別
<pre>
主要是在介紹如何利用類別class去製作一個簡單的小遊戲，
通過用類別去設定角色的各個參數值
</pre>

## [ self practice ]
* 計算每一列的字元數目
```python
"""計算每一列的字元數目"""
file = "test2.txt"
with open(file,'r') as f:
    content=f.readlines()    
   
for row in content:
    n = len(row)
    print("字元數=%2s : %s" %(n,row)) 
```

    字元數=34 : asdf g123g rt rtyuj 123tt ty12tre
    
    字元數= 9 : rth rtkw
    
    字元數= 8 : 456kwlg
    
    字元數=35 : lrm rkkmwthmtrchahahahahhahahhahaha
    
* 計算文字中有多少個h
```python
"""計算文字中有多少個h"""
file = "test2.txt"
with open(file,'r') as f:
    content=f.read()

n=0
for ch in content:
    if (ch=="H" or ch=="h"):
        n+=1
print("共有",n,"個 H 或 h 字元") 
```

    共有 13 個 H 或 h 字元
    
