خانه / آموزش‌ها / توابع eval و exec در پایتون

توابع eval و exec در پایتون

🐍 HomeOfPython
|
📅 1404/10/24

سطح مقدماتی (Beginner Level)

پایتون به عنوان یک زبان مفسری (Interpreted)، قابلیتی قدرتمند دارد که اجازه می‌دهد رشته‌های متنی (Strings) را به عنوان کد پایتون اجرا کنید. این کار توسط دو تابع داخلی eval() و exec() انجام می‌شود. در این بخش با تفاوت‌های این دو و کاربردهای ساده آن‌ها آشنا می‌شویم.

۱. تابع eval (مخصوص عبارات)

تابع eval() مخفف Evaluate است. این تابع یک رشته را می‌گیرد و آن را به عنوان یک "عبارت" (Expression) پایتون ارزیابی می‌کند و نتیجه را برمی‌گرداند.

  • نکته: عبارت کدی است که یک مقدار تولید می‌کند (مثل عملیات ریاضی، فراخوانی تابع، یا متغیر).
  • eval نمی‌تواند دستورات پیچیده مثل تعریف تابع (def) یا حلقه (for) را اجرا کند.

مثال اول: محاسبه ریاضی ساده

در این مثال یک رشته حاوی عملیات ریاضی را اجرا می‌کنیم.

Python

مثال دوم: کار با متغیرها

شما می‌توانید از متغیرهایی که در برنامه تعریف شده‌اند، درون رشته‌ی eval استفاده کنید.

Python

مثال سوم: محدودیت eval

اگر سعی کنید یک دستور (Statement) مثل انتساب متغیر (x = 5) را در eval اجرا کنید، با خطا مواجه می‌شوید.

Python

۲. تابع exec (مخصوص دستورات)

تابع exec() مخفف Execute است. این تابع برای اجرای "دستورات" (Statements) و بلوک‌های کد استفاده می‌شود.

  • exec هیچ مقداری برنمی‌گرداند (همیشه None است).
  • می‌تواند حلقه‌ها، تعریف کلاس، تعریف تابع (def)، و ایمپورت‌ها را اجرا کند.

مثال اول: اجرای یک دستور ساده

در اینجا یک متغیر جدید را درون رشته تعریف می‌کنیم.

Python

مثال دوم: اجرای بلوک کد (حلقه و شرط)

شما می‌توانید چندین خط کد را با استفاده از Triple Quotes به exec بدهید.

Python

مثال سوم: تعریف تابع به صورت پویا

می‌توانید حتی یک تابع کامل را درون یک رشته بنویسید و آن را به برنامه اضافه کنید.

Python

سطح پیشرفته (Professional Level)

استفاده از eval و exec در محیط‌های حرفه‌ای (Production) بسیار حساس است. بزرگترین چالش، امنیت و کنترل دسترسی (Scope) است. در این بخش یاد می‌گیریم چگونه محیط اجرای این توابع را ایزوله کنیم و از خطرات امنیتی جلوگیری کنیم.

۱. مدیریت Scope (Globals و Locals)

هر دو تابع eval و exec دو آرگومان اختیاری دیگر نیز می‌پذیرند:

  1. globals: دیکشنری متغیرهای سراسری مجاز.
  2. locals: دیکشنری متغیرهای محلی مجاز.

اگر این‌ها را محدود نکنید، کد مخرب می‌تواند به تمام متغیرهای برنامه شما و حتی ماژول‌های ایمپورت شده (مثل os) دسترسی داشته باشد.

مثال اول: محدود کردن دسترسی به متغیرها

در این مثال، به eval اجازه نمی‌دهیم به متغیرهای مخفی (secret) دسترسی پیدا کند.

Python

مثال دوم: تزریق توابع خاص

می‌توانید فقط توابع خاصی (مثل توابع ریاضی) را در اختیار کد پویا قرار دهید و بقیه را حذف کنید.

Python

۲. خطرات امنیتی (Injection Attacks)

شعار معروف برنامه‌نویسان پایتون این است: "Eval is Evil". اگر ورودی کاربر را مستقیماً به eval یا exec بدهید، کاربر می‌تواند کدهای مخربی مثل حذف فایل‌ها یا سرقت اطلاعات را اجرا کند.

مثال سناریوی خطرناک (تئوری)

کد زیر نشان می‌دهد چگونه یک کاربر مخرب می‌تواند ماژول os را ایمپورت کرده و دستورات سیستم عامل را اجرا کند (این کد فقط برای آموزش است و در محیط سندباکس اجرا نمی‌شود).

python
# Static Code: Security Risk Example
user_input = "__import__('os').system('rm -rf /')" # Danger!
# eval(user_input) # This would wipe files on a Linux system

۳. جایگزین امن: ast.literal_eval

اگر هدف شما فقط تبدیل یک رشته به ساختار داده پایتون (مثل تبدیل رشته "{'a': 1}" به دیکشنری) است، هرگز از eval استفاده نکنید. به جای آن از ماژول ast و تابع literal_eval استفاده کنید. این تابع فقط ساختارهای داده‌ای امن را ارزیابی می‌کند و اجازه اجرای توابع یا محاسبات را نمی‌دهد.

مثال مقایسه eval و literal_eval

Python

۴. کامپایل کد با compile()

اگر نیاز دارید یک قطعه کد پویا را چندین بار اجرا کنید، استفاده مداوم از exec کند است زیرا هر بار کد را پارس (Parse) می‌کند. بهتر است ابتدا آن را با تابع compile() به یک آبجکت کد تبدیل کنید و سپس اجرا کنید.

Python

توضیحات