วันศุกร์ที่ 15 สิงหาคม พ.ศ. 2557

ep7 python : การแตกไฟล์ .zip ด้วยพี่เหลือม (extract .zip file by coding python)

พอดีมีงานที่ต้องเขียนโค้ด โดยให้แตก .zip ออกมา โดยไม่ต้องให้ user ทำอะไรเลย แต่ user ไม่สามารถเห็นโค้ดเราได้ (และมีรายละเอียดอื่นอีก ไม่บอกแล้วกันเนอะ) เราคิดว่าพี่เหลือม ทำ .exe file ได้ เลยมาลองกับพี่เหลือมเลยคะ พี่เหลือมมี library ที่จัดการ .zip file ด้วย และมี library มากมายให้เลือกใช้

โจทย์ในประเด็นนี้คือ มี .zip อันนึง โครงสร้างภายในมี folder ชื่อเดียวกับไฟล์ แล้วค่อยเจอไส้ใน ดังนี้

ไส้ในควรมีมากกว่า 1 ไฟล์ เพื่อความชัวร์คะ
แล้วเราถามกู๋ ลองทำตามโค้ดในเว็บนึง ดังนี้

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 ชื่อไฟล์ที่เราสร้างนั้น มันมีอยู่หรือเปล่า ไม่มีก็ให้สร้าง จะได้ไม่มีปัญหา

สุดท้าย ออกเลย

import sys
import string
import zipfile
inport os

#ขอยก unzip มาแก้อันเดียวนะคะ
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():
    root, name = string.split(each,"/") //แยกส่วนคือ ส่วน path file กับชื่อไฟล์
    if len(name) == 0: //แยกโฟลเดอร์ด้านนอกออก
      continue
    else:
      directory = norm(join(path, root)) # result is .zip name, str type
        #ดูว่า มี directory นี้ไหม มีโค้ด 2 บรรทัดเองเนอะ
        if not os.path.exists(directory): #check folder exist
          os.makedirs(directory) #build folder
        #ส่วนที่ comment เป็นส่วนที่ผิดนะคะ อธิบายแต่ละบรรทัดเลย
        #b = open("D:\\mikki/work/python_zip/"+i, 'wb') #อันนี้ยัด path เข้าไปตรงๆเลย
        #b = open(directory + name, 'wb') #all files are changed file name and extract all outside (เปลี่ยนชื่อไฟล์ทั้งหมดเป็น directory และ extract ออกมาข้างนอก)
        #b = open(name, 'wb') #all files extract outside (extract ออกมาข้างนอก)
        #b = open(join(directory, name), 'wb') #have directory and extract 1 file from all (directory มาแล้ว แต่ไส้ในออกมาอันเดียวเองง่ะ)
        #b = open(each, 'wb') #have directory and extract 1 file from all เหมือนกับด้านบน
        #b = open(directory, 'wb') #no directory
        b = open(directory + '\\' + name, 'wb')
        b.write(zip.read(each))
        b.close()

ตอนนี้ก็ได้ตาม requirement เรียบร้อย ในขั้นแรก

ถ้าเราใส่ password แล้วต้องการให้ใช้โปรแกรมนี้ extract ออก ใช้คำสั่ง
zip.setpassword(<password>) ก่อน for loop นะ

การทำงาน function คือ unzip(<path>, <zip_file>)
ถ้าอยากแตกไฟล์ที่อื่น ใส่ directory ที่ต้องการ ไว้ที่ <path>
ถ้าต้องการแตกไฟล์ที่เดียวกับ zip file ให้ใส่ '' ตามตัวอย่างเลยคะ :)
>> https://github.com/mikkipastel/pythonZipAttach

ป้ายกำกับ: ,

0 ความคิดเห็น:

แสดงความคิดเห็น

สมัครสมาชิก ส่งความคิดเห็น [Atom]

<< หน้าแรก