Day 18 系統模組:走路的不是強尼,是你心中的OS
註:本篇文章同步刊載於iT邦幫忙,為鐵人賽之系列文章。https://ithelp.ithome.com.tw/articles/10246454
我們先來看看昨天的練習吧!
一般來說,我們可以先打開來觀察,
將其複製到JSON Online Editor上看看右邊的tree長什麼樣子,
這樣會有助於後面思考操作方式。
- 請下載下來並放到你自己執行的目錄(筆者命名為bookstore.json)
- 用以下的讀取方式,將json檔載入到bs裡:
1
2
3
| import json
with open('bookstore.json', 'r', encoding="utf-8") as f:
bs = json.load(f)
|
- bs是一個串列(因為在這個json裡面是以array的型式儲存的)
- 我們可以用以下的方式(或者你要去用地址找也可以)
1
2
| # 記得list comprehension嗎?
taipei = [i for i in bs if '臺北市' in i['cityName']]
|
- taipei中特色書店點閱數超過2000的店家是哪幾家呢?請列出其名字。
1
2
3
| # 我們要的是名字,所以要取'name',判斷標準則是用hitRate。
>>> [i['name'] for i in taipei if i['hitRate'] > 2000]
['茉莉二手書店(臺大店)', '信誼小太陽親子書房(臺北重慶店)', '田園城市生活風格書店', '亞典藝術書店', '古原軒書店']
|
請留意到,這個練習是相對比較輕鬆的,
因為當中所用到的元素都沒有缺漏的部分,
所以不會產生任何錯誤;
但實務狀況上,常常會有一些資料是短少的,
這時候就要先做過資料的前處理(preprocessing)以後,
將缺漏的部分去除,或者補上適當的值,才能讓資料得以正常使用。
在資料清理(data cleaning)這部分,Python常用的有pandas跟numpy,
以後我們有機會再來介紹。
我們今天要來講的是系統模組(os)。
OS是Operating System(作業系統)的縮寫,
主要作用是提供你所使用的作業系統的一些功能,
例如檔案的路徑檢查、列出檔案列表、
檔案複製/移動/改名/刪除等。
下面的示範,我們是基於使用者在以下的資料夾環境操作的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| C:\Users\Desolve\utils>tree /f
列出資料夾 PATH
磁碟區序號為 D6BD-47D7
C:.
│ bookstore.json
│ check.py
│ fromzero.py
│ poem.txt
│ schedule.py
│ __init__.py
│
├─csv
│ student.csv
│ student_dic.csv
│
├─json
│ classA.json
│
└─__pycache__
check.cpython-38.pyc
schedule.cpython-38.pyc
__init__.cpython-38.pyc
|
要使用os,最重要的就是先import啦!
請留意一件事情,
在Unix系列的系統裡面,路徑分隔資料夾或檔案是使用”/”來處理的 ,
Windows系列的系統中,則是使用”\”,兩者剛好相反 。
如果我們想看某個檔案或目錄是否存在於特定位置 ,
我們可以使用os.path.exists() ,可以是相對路徑或絕對路徑 。
相對路徑是從現在的資料夾為基準出發,來看到到目標位置要怎麼移動;
絕對路徑則是從Unix的根目錄或Windows的C槽D槽之類的起始點出發;
所以以相對路徑來起頭的,前面會有一個”./”或”.”開頭 ,
用來表示從現在所在位置起算(一個點代表現在所在位置,兩個點代表上一層)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| >>> import os
>>> os.path.exists('check.py')
True
>>> os.path.exists('poem.txt')
True
>>> os.path.exists('.\json\classA.json')
True
>>> os.path.exists('./json/classA.json') # 實際上用linux的寫法給Python去認也行得通,Python會明白含義
True
>>> os.path.exists('./json/classB.json') # 不存在就回傳False
False
>>> os.path.exists('C:\Users\Desolve\utils\json\classA.json') # 用絕對路徑時避免不必要的麻煩,請多加一個"\"將可能造成的轉義去除
File "<stdin>", line 1
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
>>> os.path.exists('C:\\Users\\Desolve\\utils\\json\\classA.json')
True
|
再來是分開來的檢查這個路徑是否是檔案/資料夾的方法:
os.path.isfile()及os.path.isdir() 。
1
2
3
4
5
6
7
8
| >>> os.path.isfile('./json/classA.json') # 存在,且是檔案
True
>>> os.path.isfile('./json/classB.json') # 不存在則回傳False
False
>>> os.path.isdir('./json/classA.json') # 是檔案,不是資料夾
False
>>> os.path.isdir('./json') # 是資料夾
True
|
那麼如果想要複製或移動檔案呢?這就要用到另一個模組shutil 了:
1
2
3
4
5
| >>> import shutil
>>> shutil.copy('poem.txt', 'poem2.txt') # 前面是來源,後面是目的地
'poem2.txt'
>>> shutil.move('poem2.txt', 'poem3.txt') # 移動檔案並更名
'poem3.txt'
|
要修改名字的話,則可以使用os.rename() :
1
| >>> os.rename('./json/poem3.txt', 'poem3.txt') # 也可以做為移動檔案用
|
要新增/刪除資料夾的話,可以使用os.mkdir()/os.rmdir() ,
刪除檔案則使用os.remove() :
(有沒有覺得跟Unix系統的shell script很像呢XD?)
1
2
3
4
5
6
7
8
| >>> os.mkdir('poems') # 開一個新的資料夾
>>> os.rename('poem3.txt', './poems/poem3.txt') # 將poem3.txt移入
>>> os.rmdir('poems') # 將poems資料夾刪除...咦?
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [WinError 145] 目錄不是空的。: 'poems'
>>> os.remove('poems/poem3.txt') # 只能先將檔案移除
>>> os.rmdir('poems') # 再移除資料夾
|
讀者可能會問:
「我怎麼會知道要先刪除哪些檔案?」
問的好!我們可以使用os.listdir()先列出資料夾的所有檔案及資料夾 :
(注意,只會列出第一層的,再往下的子資料夾就不會展開囉!)
1
2
3
4
| >>> os.listdir()
['bookstore.json', 'check.py', 'csv', 'fromzero.py', 'json', 'poem.txt', 'schedule.py', '__init__.py', '__pycache__']
>>> os.listdir('csv')
['student.csv', 'student_dic.csv']
|
最後,是我們的終極必殺武器:os.walk() 。
os.walk()就像一個偏執的用路人一樣,
它就是要將整個資料夾,連同子資料夾都走過一遍才會罷休。
走完之後,所有的內容會以(dirpath, dirnames, filenames)的形式回傳,
我們可以使用for … in …的方式取得,
請看範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| for root, dirs, files in os.walk('.'): # os.walk必須要給一個起始點
print(root)
for f in files:
print(os.path.join(root, f)) # os.path.join()可用來處理路徑和檔案的結合
# 結果如下
.
.\bookstore.json
.\check.py
.\fromzero.py
.\poem.txt
.\schedule.py
.\__init__.py
.\csv
.\csv\student.csv
.\csv\student_dic.csv
.\json
.\json\classA.json
.\__pycache__
.\__pycache__\check.cpython-38.pyc
.\__pycache__\schedule.cpython-38.pyc
.\__pycache__\__init__.cpython-38.pyc
|
如果想要刪除掉某個目錄以下的所有檔案及資料夾,
可以參考Python的Document提供的範例:
請特別留意慎用以下操作,
底下的動作可是真的會將目標資料夾全刪光的!!!
尤其是Unix系列的系統,
如果給的top起始點是”/”(根目錄)而非”./”(當前目錄),
則會將整個檔案系統都砍光光呦!!!
1
2
3
4
5
| for root, dirs, files in os.walk(top, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
|
今天我們介紹了os中跟檔案系統相關操作有關的方法,
其他當然也有很多不錯的相關模組,
例如剛剛有提到的shutil ,或是pathlib ,
有興趣的讀者可再行挖掘。
那麼,我們就明天見囉!
工商時間:
抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)
在Python Taiwan的連結第100篇的文章 底下,
公開分享到你的臉書、按讚該篇文章、並留言告訴我說,
「你最喜歡這一整個系列的哪一篇?為什麼?」或
「除了從LeetCode學演算法系列以外,
你還想要看到關於什麼方向的文章?」
超過20則留言的話 (有完成以上步驟的才算),我們就抽一組
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」
課程的免費兌換券進行贈送!
期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)
容筆者工商一下,
「從Leetcode學演算法|進階篇」 開放預購啦!
這次選了40道難度加深的LeetCode題目,
同樣也會細部解說對應的技巧及須要掌握的演算法!
同時這次購買進階篇的話,
額外還加贈**「從Leetcode學演算法|面試篇」** !
當中包含了面試準備須知分享 ,及訪談國內外不同經驗的工程師 ,
讓你不論是想走前端/後端/一般軟工 或者是想找國外的工作 ,
是初學想轉職 還是正在工作 ,都能夠從中得到收穫呦!
有興趣的朋友可以使用下面的早鳥優惠~
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」 :
https://bit.ly/leetcodeadv
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠:
https://bit.ly/leetcodeall