ep7 python : การแตกไฟล์ .zip ด้วยพี่เหลือม (extract .zip file by coding python)
พอดีมีงานที่ต้องเขียนโค้ด โดยให้แตก .zip ออกมา โดยไม่ต้องให้ user ทำอะไรเลย แต่ user ไม่สามารถเห็นโค้ดเราได้ (และมีรายละเอียดอื่นอีก ไม่บอกแล้วกันเนอะ) เราคิดว่าพี่เหลือม ทำ .exe file ได้ เลยมาลองกับพี่เหลือมเลยคะ พี่เหลือมมี library ที่จัดการ .zip file ด้วย และมี library มากมายให้เลือกใช้
โจทย์ในประเด็นนี้คือ มี .zip อันนึง โครงสร้างภายในมี folder ชื่อเดียวกับไฟล์ แล้วค่อยเจอไส้ใน ดังนี้
แล้วเราถามกู๋ ลองทำตามโค้ดในเว็บนึง ดังนี้
import os, zipfile
def unzip(path, zip):
isdir = os.path.isdir
join = os.path.join
norm = os.path.normpath
split = os.path.split
for each in zip.namelist():
if not each.endswith('/'):
root, name = split(each)
directory = norm(join(path, root))
if not isdir(directory):
os.makedirs(directory)
file(join(directory, name), 'wb').write(zip.read(each))
if __name__ == '__main__':
zip = zipfile.ZipFile('Python.zip', 'r')
unzip('', zip)
zip.close()
อธิบายเพิ่มเติม
zip.namelist()
ดูว่าใน zip file ของเรานั้น ไส้ในมีไฟล์อะไรบ้างos.makedirs(directory)
สร้าง directory มีอีกตัวคือos.mkdir(directory, 0777)
ตัวเลขคือ mode ของเขา ใส่อะไรไปก็ได้ ค่ามาตรฐานของเขาคือ 0777- ตัว zip จะมีการเรียกไฟล์โดยใช้
zipfile.ZipFile('ชื่อไฟล์', 'โหมดการอ่าน')
โดยมี file permission 3 ตัว คือ 'r' read, 'w' write และ 'a' execute โดยการยัดไฟล์เข้า zip ใช้คำสั่งzip.write('ไฟล์ที่เราต้องการใส่')
เมื่อเปิดแล้ว จะมีการปิด คือzip.close()
- ในตัวอย่าง มีการ split โดยใช้ library ของ os เป็นอีกวิธีนอกจากใช้ library ของ string ซึ่งจะมีตัวอย่างในโค้ดอันหลังคะ ให้ผลเหมือนกัน
- join (os.path.join)เป็นการรวม 2 string เข้าด้วยกัน โดยมี "\\" คั่นระหว่าง 2 string นั้น เช่น
>>> join("test", "test33")
'test\\test33'
- ส่วน norn (os.path.normpath) อันนี้เป็นการ link path directory ตามความเข้าใจของเรานะ
ในเว็บพี่เหลือมมีการอธิบาย library os ลองอ่านดูเพื่อความเข้าใจมากขึ้น
ปรากฏว่า extract ได้แค่ไฟล์แรกในนั้น โค้ดเหมือนจะถูกหมด เลยลองถูกลองผิดกันไป
เปลี่ยนโค้ดไปเรื่อยๆ พบว่า ติดปัญหาที่ folder ชื่อไฟล์ที่สร้างขึ้นเอง มีปัญหา Permission denied
เลยลองตรวจดูว่า folder ชื่อไฟล์ที่เราสร้างนั้น มันมีอยู่หรือเปล่า ไม่มีก็ให้สร้าง จะได้ไม่มีปัญหา
สุดท้าย ออกเลย
ตอนนี้ก็ได้ตาม requirement เรียบร้อย ในขั้นแรก
ถ้าเราใส่ password แล้วต้องการให้ใช้โปรแกรมนี้ extract ออก ใช้คำสั่ง zip.setpassword(<password>)
ก่อน for loop นะ
การทำงาน function คือ unzip(<path>, <zip_file>)
ถ้าอยากแตกไฟล์ที่อื่น ใส่ directory ที่ต้องการ ไว้ที่ <path>
ถ้าต้องการแตกไฟล์ที่เดียวกับ zip file ให้ใส่ '' ตามตัวอย่างเลยคะ :)