FA-TOOLS — Header Component

ساخت فایل ZIP با پایتون — کد فشرده‌سازی آماده

خلاصه کلیدی این راهنما:

  • یادگیری کار با کتابخانه استاندارد zipfile بدون نیاز به نصب هیچ ابزار جانبی.
  • کد آماده برای فشرده‌سازی تکی فایل‌ها و آرشیو کردن کامل پوشه‌ها به همراه زیرپوشه‌ها.
  • بررسی مشکلات مربوط به نام‌گذاری فارسی (Unicode) و فشرده‌سازی در حافظه (بدون ذخیره روی هارد).

فشرده‌سازی فایل‌ها یکی از نیازهای همیشگی در توسعه نرم‌افزار، پشتیبان‌گیری خودکار و ارسال داده‌ها در وب است. پایتون با داشتن کتابخانه داخلی zipfile این کار را بدون نیاز به نصب هیچ پکیج اضافی، بسیار ساده و سریع کرده است. در این مقاله جامع، کدهای آماده و بهینه برای فشرده‌سازی فایل‌ها و پوشه‌ها را با هم بررسی می‌کنیم.

سریع‌ترین راه ساخت فایل ZIP در پایتون چیست؟

ساخت فایل ZIP با پایتون — کد فشرده‌سازی آماده — تصویر 1

پاسخ کوتاه: برای ساخت سریع یک فایل ZIP در پایتون، باید از کلاس ZipFile در حالت نوشتن ('w') استفاده کنید و فایل‌های مورد نظر خود را با متد write() به آن اضافه کنید. استفاده از مدیریت‌کننده متن (دستور with) امنیت بسته‌شدن فایل را تضمین می‌کند.

کد زیر یک مثال ساده و آماده برای فشرده‌سازی دو فایل متنی مجزا درون یک فایل آرشیو به نام archive.zip است:

import zipfile

# ساخت یک فایل zip جدید و اضافه کردن فایل‌ها به آن
with zipfile.ZipFile('archive.zip', 'w', compression=zipfile.ZIP_DEFLATED) as zipf:
    zipf.write('document.txt')
    zipf.write('image.png')

print("فایل ZIP با موفقیت ساخته شد!")

در کد بالا، پارامتر compression=zipfile.ZIP_DEFLATED به پایتون می‌گوید که فایل‌ها را واقعاً فشرده کند. اگر این پارامتر را ننویسید، فایل‌ها فقط درون آرشیو کپی می‌شوند و حجم آن‌ها کاهش نمی‌یابد.

فشرده‌سازی کل یک پوشه (Directory) به صورت بازگشتی

ساخت فایل ZIP با پایتون — کد فشرده‌سازی آماده — تصویر 2

بسیاری از اوقات می‌خواهید یک پوشه کامل را به همراه تمام فایل‌ها، زیرپوشه‌ها و ساختار درختی آن فشرده کنید. برای این کار باید از کتابخانه os برای پیمایش پوشه (Recursive Traversal) استفاده کنیم.

اشتباه رایج برنامه‌نویسان تازه‌کار این است که مسیرهای مطلق فایل‌ها را درون زیپ ذخیره می‌کنند؛ این کار باعث می‌شود هنگام استخراج فایل زیپ، تمام پوشه‌های تو در توی سیستم شما روی سیستم مقصد بازسازی شوند! کد زیر با استفاده از os.path.relpath این مشکل را کاملاً حل کرده است:

import os
import zipfile

def zip_directory(folder_path, output_zip_path):
    with zipfile.ZipFile(output_zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for root, dirs, files in os.walk(folder_path):
            for file in files:
                # ایجاد مسیر کامل فایل برای خواندن
                full_path = os.path.join(root, file)
                # ایجاد مسیر نسبی برای ذخیره در فایل ZIP (بدون مسیرهای والد اضافی)
                relative_path = os.path.relpath(full_path, folder_path)
                zipf.write(full_path, relative_path)

# روش استفاده:
zip_directory('my_project_folder', 'backup.zip')
print("پوشه مورد نظر با حفظ ساختار داخلی فشرده شد.")

مقایسه متدهای فشرده‌سازی در پایتون

ساخت فایل ZIP با پایتون — کد فشرده‌سازی آماده — تصویر 3

ماژول zipfile از چندین الگوریتم فشرده‌سازی پشتیبانی می‌کند. انتخاب درست این الگوریتم می‌تواند تاثیر چشمگیری روی سرعت اجرا و حجم نهایی فایل خروجی داشته باشد.

متد فشرده‌سازی (Constant) کاربرد و ویژگی‌ها
ZIP_STORED بدون هیچ فشرده‌سازی. فایل‌ها فقط کنار هم آرشیو می‌شوند. سرعت فوق‌العاده بالا اما حجم فایل تغییری نمی‌کند.
ZIP_DEFLATED استانداردترین متد فشرده‌سازی ZIP (zlib). تعادل عالی میان سرعت و میزان فشرده‌سازی. توصیه شده برای مصارف عمومی.
ZIP_BZIP2 قدرت فشرده‌سازی بیشتر نسبت به Deflated، اما سرعت اجرای آن کمتر است و مصرف منابع بالاتری دارد.
ZIP_LZMA بسیار قدرتمند با بیشترین نرخ فشرده‌سازی ممکن. سرعت فشرده‌سازی کند است اما برای آرشیوهای حجیم عالی است.

۴ نکته حرفه‌ای و محدودیت‌های پنهان zipfile

ساخت فایل ZIP با پایتون — کد فشرده‌سازی آماده — تصویر 4

برای نوشتن کدهای صنعتی و بدون باگ، دانستن این جزییات تخصصی حیاتی است:

۱. حل مشکل کاراکترهای فارسی (Non-ASCII) در نام فایل‌ها

به صورت پیش‌فرض، اگر نام فایل‌های شما فارسی باشد، ممکن است بعد از باز کردن ZIP در سیستم‌عامل‌های دیگر با کاراکترهای به‌هم‌ریخته مواجه شوید. پایتون به طور پیش‌فرض نام فایل‌ها را با کدگذاری CP437 یا UTF-8 ذخیره می‌کند. برای سازگاری کامل، همیشه مطمئن شوید که سیستم عامل مقصد نیز از یونیکد پشتیبانی می‌کند؛ در پایتون ۳ این کار به طور خودکار انجام می‌شود اما بهتر است فایل‌های خود را از قبل تمیزکاری کنید.

۲. فشرده‌سازی در حافظه (Memory Buffer) بدون ذخیره روی دیسک

اگر در حال توسعه یک وب‌اپلیکیشن (مثل جنگو یا FastAPI) هستید و می‌خواهید فایلی را زیپ کرده و مستقیماً برای کاربر ارسال کنید، نوشتن آن روی هارد دیسک سرور کارآمد نیست. شما می‌توانید با استفاده از کلاس io.BytesIO عملیات فشرده‌سازی را کاملاً در حافظه موقت (RAM) انجام دهید. برای یادگیری ترفندهای بیشتر این‌چنینی، می‌توانید قطعه کدهای پایتون را در بخش کدهای آماده دنبال کنید.

import io
import zipfile

# ایجاد یک بافر در حافظه RAM
memory_zip = io.BytesIO()

with zipfile.ZipFile(memory_zip, 'w', zipfile.ZIP_DEFLATED) as zipf:
    # نوشتن مستقیم متن در قالب فایل درون زیپ بدون وجود فیزیکی فایل روی دیسک
    zipf.writestr('dynamic_file.txt', 'این یک فایل تست در حافظه است.')

# دریافت بایت‌های نهایی فایل زیپ
zip_data = memory_zip.getvalue()

۳. محدودیت رمزگذاری (Encryption) در کتابخانه استاندارد پایتون

کتابخانه پیش‌فرض zipfile می‌تواند فایل‌های زیپ رمزگذاری شده قدیمی (ZipCrypto) را بخواند، اما نمی‌تواند فایل زیپ با پسورد AES (استاندارد امن مدرن) تولید کند. اگر به رمزگذاری قوی نیاز دارید، نباید از zipfile استاندارد استفاده کنید؛ در عوض باید سراغ کتابخانه‌های جانبی مثل pyzipper بروید.

۴. جایگزین فوق‌سریع: استفاده از shutil برای فشرده‌سازی‌های ساده

اگر نیازی به کنترل تک‌تک فایل‌ها ندارید و فقط می‌خواهید یک خط کد بنویسید که کل یک پوشه را بدون دردسر فشرده کند، کتابخانه استاندارد shutil بهترین گزینه است:

import shutil
# ساخت فایل zip از کل پوشه پروژه در یک خط کد
shutil.make_archive('output_archive_name', 'zip', 'directory_to_compress')

عیب‌یابی سریع خطاهای رایج

خطای: BadZipFile: File is not a zip file

علت: این خطا معمولاً زمانی رخ می‌دهد که می‌خواهید فایلی را باز کنید که خراب شده یا به طور کامل دانلود/ساخته نشده است. همچنین اگر فایلی را در حالت نوشتن ('w') باز کرده باشید و قبل از اتمام کار، اسکریپت کرش کند، این خطا رخ می‌دهد. همیشه از ساختار with استفاده کنید تا فایل به درستی بسته (Close) شود.

خطای: Large Zip file takes too much memory

علت: فشرده‌سازی فایل‌های چند گیگابایتی به یک‌باره می‌تواند رم سیستم را پر کند. برای جلوگیری از این مشکل، فایل‌ها را به صورت تک به تک و به شکل استریم (Stream) درون آرشیو بنویسید و از الگوریتم پیش‌فرض ZIP_DEFLATED استفاده کنید.

پرسش‌های متداول

چطور می‌توان یک فایل جدید را به فایل ZIP موجود اضافه (Append) کرد؟

کافی است به جای حالت 'w'، فایل آرشیو را در حالت 'a' (مخفف Append) باز کنید. به این ترتیب فایل‌های قبلی پاک نمی‌شوند و فایل جدید به انتهای آرشیو اضافه می‌شود.

آیا پایتون بدون ابزار خارجی می‌تواند فایل‌های ZIP پسورددار بسازد؟

خیر، متاسفانه کتابخانه استاندارد zipfile در هنگام نوشتن فایل‌های زیپ، از تنظیم پسورد امن (مانند رمزگذاری AES-256) پشتیبانی نمی‌کند. برای این کار باید از کتابخانه جانبی pyzipper استفاده کنید.

چگونه کل محتویات یک فایل زیپ را استخراج (Extract) کنیم؟

برای استخراج کامل می‌توانید از متد extractall() استفاده کنید. به عنوان مثال: with zipfile.ZipFile('file.zip', 'r') as zip_ref: zip_ref.extractall('destination_folder').

تفاوت zipfile و shutil در فشرده‌سازی چیست؟

ماژول shutil سطح بالا‌تر است و برای فشرده‌سازی‌های سریع کل یک پوشه بدون شخصی‌سازی مناسب است. در مقابل، zipfile به شما کنترل دقیق روی تک‌تک فایل‌ها، ساختار درونی آرشیو، سطح فشرده‌سازی و متادیتاها را می‌دهد.

Table of Contents

آخرین نوشته‌ها

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *