یک بار، وقتی به یک توسعه‌دهنده‌ی تازه‌کار کمک می‌کردم، کد او در IDE کاملاً درست به‌نظر می‌رسید ولی Python با یک خطای عجیب اجرا نمی‌شد: IndentationError: unexpected indent. وقتی فایل را در یک ویرایشگر با نمایش فضای سفید باز کردم، فهمیدم که در برخی خطوط، Tab و در برخی دیگر Space استفاده شده بود. آن روز، تفاوت بین خطای ظاهری و خطای واقعی را به‌طور جدی یاد گرفتم. خطای IndentationError در Python یکی از آن خطاهایی است که برای تازه‌کارها گیج‌کننده و برای حرفه‌ای‌ها نشانه‌ی سهل‌انگاری در تنظیمات محیط است.

خطای IndentationError در Python دقیقاً چیست؟

Python یکی از آن زبان‌های برنامه‌نویسی است که به‌جای استفاده از براکت‌های نوشتاری برای تعریف بلوک‌های کد، از تورفتگی (indentation) استفاده می‌کند. این طراحی، کد را خواناتر می‌کند ولی در عین حال، خطاهای ظریفی را ممکن می‌سازد. خطای IndentationError در Python زمانی مطرح می‌شود که تورفتگی کد شما با قواعد زبان سازگار نباشد. پیام خطا معمولاً چنین شکلی دارد:

  File "script.py", line 5
    print("Hello")
    ^
IndentationError: unexpected indent

نکته‌ی کلیدی در این پیام، بخش IndentationError: است. بعد از این عبارت، نوع دقیق خطا می‌آید. رایج‌ترین انواع:

  • unexpected indent: کدی که نباید تو رفته باشد، تو رفته.
  • expected an indented block: کدی که باید تو رفته باشد، تو نرفته.
  • unindent does not match any outer indentation level: تورفتگی با هیچ سطح بیرونی مطابقت ندارد.
  • inconsistent use of tabs and spaces: ترکیب Tab و Space در یک فایل.
  • unindent to a level that does not match any outer indentation level: کاهش تورفتگی به سطحی که معتبر نیست.

این خطا از نوع SyntaxError است، یعنی در زمان parse کد رخ می‌دهد، نه در زمان اجرا. به‌همین دلیل، حتی اگر بخشی از کد شما اجرا نشود (مثلاً در یک شرط if False)، خطای تورفتگی باز هم مطرح می‌شود.

اگر با مبانی Python آشنایی ندارید، ابتدا آموزش پایتون از صفر را بخوانید تا مدل ذهنی درستی از ساختار کد شکل بگیرد.

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

چرا Python به تورفتگی اهمیت می‌دهد؟

بیشتر زبان‌های برنامه‌نویسی، از براکت‌های نشانه‌گذاری برای تعریف بلوک‌های کد استفاده می‌کنند. مثلاً در C یا Java، بلوک کد با { و } مشخص می‌شود. در JavaScript، همین قواعد. در Ruby، از end استفاده می‌شود.

Python یک مسیر متفاوت را انتخاب کرد: تورفتگی، بخشی از گرامر زبان است. این تصمیم، از فلسفه‌ی Python می‌آید که در مستندات رسمی زبان به‌عنوان The Zen of Python شناخته می‌شود:

Readability counts.
Beautiful is better than ugly.

در این فلسفه، خواناتر بودن کد، یک اصل است. براکت‌های نوشتاری، اگرچه برای کامپایلر معنی دارند، برای چشم انسان فقط نویز هستند. Python با حذف این براکت‌ها و استفاده از تورفتگی، کد را برای انسان خواناتر می‌کند.

نکته‌ی ظریف: این تصمیم، مزایا و معایب خود را دارد. مزیت اصلی، خواناتر بودن کد است. عیب اصلی، ایجاد خطاهای ظریف برای کسانی که از زبان‌های دیگر می‌آیند یا تنظیمات ویرایشگرشان به‌درستی تنظیم نشده است. در تجربه‌ی من، این خطا در دو گروه شایع است: توسعه‌دهنده‌های تازه‌کار و توسعه‌دهنده‌هایی که از زبان‌های دیگر مهاجرت می‌کنند.

تورفتگی به‌عنوان بخشی از گرامر Python

برای درک درست این خطا، باید بفهمیم که تورفتگی در Python چگونه parse می‌شود. Parser Python، پیش از parse کد، دو مرحله‌ی مخصوص برای تورفتگی دارد:

مرحله اول: tokenize. Python کد را به tokenها تبدیل می‌کند. در این مرحله، تورفتگی‌ها به‌عنوان tokenهای خاص INDENT و DEDENT شناسایی می‌شوند.

مرحله دوم: parse. در مرحله‌ی parse، این tokenها برای تعریف بلوک‌های کد استفاده می‌شوند. اگر تورفتگی‌ها درست نباشند، parse شکست می‌خورد.

نکته‌ی مهم این است که Python، عرض تورفتگی را در هر بلوک ثابت نگه می‌دارد. یعنی اگر در یک بلوک، از 4 space استفاده کرده‌اید، در بقیه‌ی بلوک‌ها هم باید از همان استفاده کنید. ترکیب 4 space در یک جا و 2 space در جای دیگر، خطا می‌دهد.

علاوه بر این، Python با Tab و Space رفتار متفاوتی دارد. اگرچه می‌توانید از هر دو استفاده کنید، ولی ترکیب آن‌ها در یک فایل خطا می‌دهد. به‌همین دلیل، در جامعه‌ی Python، استاندارد استفاده از Space به‌جای Tab است، که در خطای SyntaxError در Python هم به آن اشاره شده است.

پنج شکل رایج IndentationError

در تجربه‌ی من، این خطا در پنج شکل مشخص ظاهر می‌شود. شناخت این شکل‌ها، تشخیص را در چند ثانیه ممکن می‌کند.

شکل اول: unexpected indent

شایع‌ترین شکل. این خطا وقتی رخ می‌دهد که کد شما در جایی که نباید تو رفته، تو رفته باشد. مثال:

def greet():
    print("Hello")

    print("World")  # unexpected indent

    print("!")

در این مثال، خط آخر خطا می‌دهد چون Python انتظار ندارد بعد از بلوک تابع، تورفتگی وجود داشته باشد.

شکل دوم: expected an indented block

وقتی که کد شما در جایی که باید تو رفته باشد، تو نرفته باشد. مثال:

def greet():
print("Hello")  # expected an indented block

در این مثال، Python انتظار دارد که بدنه‌ی تابع greet تو رفته باشد.

شکل سوم: unindent does not match any outer indentation level

وقتی که کاهش تورفتگی شما با هیچ سطح بیرونی مطابقت ندارد. مثال:

def greet():
    if True:
        print("Hello")
      print("World")  # unindent mismatch

در این مثال، خط آخر با 6 space تو رفته، در حالی که هیچ سطح بیرونی با 6 space وجود ندارد.

شکل چهارم: inconsistent use of tabs and spaces in indentation

وقتی که در یک فایل، ترکیبی از Tab و Space استفاده شده باشد. این خطا در IDEهایی که Tab را به‌طور خودکار به Space تبدیل می‌کنند ممکن است دیده نشود، ولی در ویرایشگرهای متن ساده (مثل nano یا Vim) شایع است.

شکل پنجم: unindent to a level that does not match

شکل خاصی از عدم تطابق، که وقتی رخ می‌دهد که شما به سطحی از تورفتگی بازگردید که در سلسله‌مراتب بلوک‌ها وجود ندارد.

Unexpected indent

این شکل، پرتکرارترین IndentationError است. علت اصلی، اشتباه در تعداد یا نوع تورفتگی در یک خط. راه‌حل:

# اشتباه
def greet():
    print("Hello")
        print("World")  # unexpected indent

# درست
def greet():
    print("Hello")
    print("World")

در برخورد با این خطا، اولین کار این است که خط مورد اشاره و خط قبل از آن را در یک ویرایشگر با نمایش whitespace باز کنید. اکثر IDEها امکان نمایش whitespace را دارند. با این نمایش، فوراً مشخص می‌شود که کدام خط تورفتگی اشتباه دارد.

Expected an indented block

این خطا وقتی رخ می‌دهد که یک بلوک کد (تابع، شرط، حلقه) با : تمام شده ولی بدنه‌اش تو نرفته است. مثال:

# اشتباه
if True:
print("Yes")

# درست
if True:
    print("Yes")

راه‌حل: بعد از :، باید خط بعد تو رفته باشد. اگر می‌خواهید بلوک خالی باشد، از pass استفاده کنید:

if True:
    pass

Unindent does not match any outer indentation level

این خطا زمانی رخ می‌دهد که تورفتگی شما به سطحی کاهش می‌یابد که با هیچ سطح بیرونی مطابقت ندارد. مثال:

def greet():
    if True:
        print("Hello")
      print("World")  # unindent mismatch

خط آخر با 6 space تو رفته، در حالی که سلسله‌مراتب فعلی یا باید در 4 space باشد (سطح تابع) یا در 8 space (سطح شرط). 6 space معتبر نیست.

راه‌حل: بررسی دقیق تعداد space در خطوط مجاور و تطبیق با ساختار کلی. ابزارهای نمایش whitespace در این مورد کمک‌کننده‌اند.

ترکیب Tab و Space

یکی از مزمن‌ترین مشکلات تورفتگی، ترکیب Tab و Space در یک فایل است. این مشکل به‌خصوص در پروژه‌هایی که چند توسعه‌دهنده با تنظیمات ویرایشگر متفاوت کار می‌کنند، شایع است.

Python با Tab و Space رفتار متفاوتی دارد. در Python 3، Tab و Space در یک فایل، معادل‌های متفاوتی دارند و خطا می‌دهند. در Python 2، Tab معادل 8 space بود که مشکل سازگاری ایجاد می‌کرد.

راه‌حل اصولی: در تمام فایل‌های یک پروژه، از یک نوع تورفتگی استفاده کنید. استاندارد PEP 8، استفاده از Space را توصیه می‌کند.

Inconsistent use of tabs and spaces in indentation

پیام صریح این خطا:

IndentationError: inconsistent use of tabs and spaces in indentation

راه‌حل: تشخیص و رفع ترکیب. روش‌ها:

  • استفاده از ابزارهای خط فرمان مثل sed یا expand برای تبدیل Tab به Space.
  • استفاده از IDEهای پیشرفته (PyCharm، VS Code) که whitespace را نمایش می‌دهند.
  • استفاده از ابزار autopep8 یا black برای بازفرمت خودکار فایل.

الگوی بازفرمت با black:

black script.py

این ابزار، فایل را با استاندارد PEP 8 بازنویسی می‌کند و مشکلات تورفتگی را حل می‌کند.

Tab یا Space: کدام درست است؟

در جامعه‌ی Python، این بحث از قدیم الایام وجود داشته است. ولی استاندارد رسمی (PEP 8) و اکثریت جامعه، Space را توصیه می‌کنند.

دلایل توصیه به Space:

  • یکنواختی: عرض Tab در ویرایشگرهای مختلف متفاوت است. Space در همه‌جا یکسان است.
  • پیشگیری از ترکیب: استفاده از Space، ترکیب Tab و Space را حذف می‌کند.
  • استاندارد جامعه: اکثر پروژه‌های Python از 4 Space استفاده می‌کنند.
  • ابزارهای خودکار: ابزارهایی مثل black و flake8 بر اساس 4 Space کار می‌کنند.

ولی از نظر فنی، Python با Tab هم کار می‌کند. تفاوت اصلی، در یکنواختی و سازگاری با ابزارها است. اصول کامل در آموزش پایتون از صفر آمده است.

PEP 8 و قواعد رسمی تورفتگی

PEP 8 سند رسمی سبک کدنویسی Python است. این سند، قواعد دقیق تورفتگی را تعریف می‌کند:

قاعده اول: استفاده از 4 Space به‌عنوان واحد تورفتگی.

قاعده دوم: عدم استفاده از Tab به‌طور پیش‌فرض.

قاعده سوم: حداکثر طول خط 79 کاراکتر (یا 99 در پروژه‌های مدرن‌تر).

قاعده چهارم: برای خطوط بلند، از پرانتز و شکست خط استفاده کنید، نه continuation با backslash.

رعایت این قواعد، کد شما را با اکوسیستم Python سازگار نگه می‌دارد و بخش بزرگی از خطاهای تورفتگی را پیشگیری می‌کند.

تنظیمات ویرایشگر و پیشگیری

در تجربه‌ی من، بهترین راه پیشگیری از IndentationError، تنظیم درست ویرایشگر است. تنظیماتی که در تمام ویرایشگرها توصیه می‌شود:

VS Code

در فایل .vscode/settings.json پروژه:

{
    "editor.insertSpaces": true,
    "editor.tabSize": 4,
    "editor.detectIndentation": false,
    "editor.renderWhitespace": "boundary",
    "python.formatting.provider": "black"
}

PyCharm

در Settings → Editor → Code Style → Python:

  • Tab size: 4
  • Indent: 4
  • Continuation indent: 8
  • Use tab character: unchecked

Vim

در فایل .vimrc:

set expandtab
set tabstop=4
set shiftwidth=4
set softtabstop=4

این تنظیمات، Tab را به‌طور خودکار به Space تبدیل می‌کنند و تورفتگی 4 Space را اعمال می‌کنند.

روش تشخیص اصولی در سه گام

در تجربه‌ی من، تشخیص این خطا در چند ثانیه انجام می‌شود، اگر روش سیستماتیک داشته باشید:

گام اول: خواندن دقیق پیام خطا. پیام دقیقاً می‌گوید کدام خط مشکل دارد و چه نوع مشکل است. این دو داده، جهت جستجو را تعیین می‌کند.

گام دوم: نمایش whitespace. در ویرایشگر، گزینه‌ی نمایش whitespace را فعال کنید. در VS Code: View → Render Whitespace. در PyCharm: View → Active Editor → Show Whitespaces. با این نمایش، فوراً مشخص می‌شود که کدام خط تورفتگی اشتباه دارد.

گام سوم: بررسی خطوط مجاور. خط مورد اشاره و خطوط قبل و بعد از آن را بررسی کنید. در بیشتر موارد، ریشه در تفاوت تورفتگی بین این خطوط است.

ابزارهای تشخیص:

  • python -m py_compile script.py: کامپایل فایل بدون اجرا، برای شناسایی خطاهای Syntax.
  • flake8 script.py: لینتر Python که خطاهای سبک و تورفتگی را تشخیص می‌دهد.
  • black script.py --check: بررسی اینکه فایل با استاندارد black سازگار است یا نه.
  • pylint script.py: لینتر کامل Python با تشخیص انواع خطاها.

این ابزارها، بخش بزرگی از IndentationErrorها را قبل از اجرا کشف می‌کنند.

راهبردهای رفع اصولی

بعد از تشخیص، نوبت به رفع می‌رسد. راهبردهای رفع، بر اساس نوع خطا متفاوت است:

راهبرد اول: بازفرمت خودکار

ابزار black، فایل را با استاندارد PEP 8 بازنویسی می‌کند. این رویکرد، در بیشتر موارد، خطاهای تورفتگی را حل می‌کند:

pip install black
black script.py

مزیت: سریع، استاندارد، یکنواخت. معایب: ممکن است تغییرات زیادی در فایل ایجاد کند که در diff دیده می‌شوند.

راهبرد دوم: تبدیل Tab به Space

در Linux/Mac، ابزار expand:

expand -t 4 script.py > script_fixed.py

در داخل Python:

with open("script.py") as f:
    content = f.read()
content = content.replace("\t", "    ")
with open("script.py", "w") as f:
    f.write(content)

راهبرد سوم: تنظیم مجدد تورفتگی به‌صورت دستی

برای فایل‌های کوچک، بازنویسی دستی تورفتگی‌های مشکل‌دار کارساز است. با نمایش whitespace، خطاها را یکی‌یکی اصلاح کنید.

راهبرد چهارم: استفاده از IDEهای پیشرفته

IDEهایی مثل PyCharm و VS Code، گزینه‌ی «Reformat Code» دارند که فایل را با استاندارد بازنویسی می‌کند. در VS Code: Shift+Alt+F. در PyCharm: Ctrl+Alt+L.

راهبرد پنجم: راه‌اندازی pre-commit hook

برای پروژه‌های تیمی، استفاده از pre-commit hook که پیش از هر commit، فایل‌ها را با black بازفرمت می‌کند:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/psf/black
    rev: 23.1.0
    hooks:
      - id: black

این رویکرد، یکنواختی کد را در تیم تضمین می‌کند و از IndentationErrorها پیشگیری می‌کند.

پرسش‌های پرتکرار درباره خطای IndentationError

این پرسش‌ها از دل تجربه‌ی عملی و جلسات مشاوره جمع‌آوری شده‌اند. پاسخ هر کدام بر اساس سناریوهای واقعی است.

تفاوت IndentationError و TabError چیست؟

IndentationError یک کلاس عمومی است که خطاهای تورفتگی را پوشش می‌دهد. TabError یک زیرکلاس از IndentationError است که به‌طور خاص برای ترکیب Tab و Space استفاده می‌شود. بنابراین، هر TabError یک IndentationError هم هست، ولی برعکسش نه.

چرا این خطا در زمان اجرا رخ می‌دهد نه در زمان کامپایل؟

در Python، IndentationError در زمان parse کد رخ می‌دهد، نه در زمان اجرا. در حقیقت، Python فایل را خط‌به‌خط parse می‌کند و اگر در خطی خطای تورفتگی باشد، همان‌جا متوقف می‌شود. به‌همین دلیل، این خطا حتی اگر بخشی از کد اجرا نشود، رخ می‌دهد.

آیا استفاده از Tab اشتباه است؟

از نظر فنی، نه. Python با Tab هم کار می‌کند. ولی استاندارد PEP 8 و اکثریت جامعه، Space را توصیه می‌کنند. دلیل: یکنواختی و سازگاری با ابزارها. اگر از Tab استفاده می‌کنید، در تمام فایل یکنواخت باشید و از ترکیب با Space خودداری کنید.

چطور می‌توانم whitespace را در ویرایشگر ببینم؟

در VS Code: View → Render Whitespace یا در تنظیمات editor.renderWhitespace: boundary. در PyCharm: View → Active Editor → Show Whitespaces. در Vim: :set list. در Sublime Text: View → Show Console و سپس view.settings().set("draw_white_space", "all").

آیا black می‌تواند همه‌ی IndentationErrorها را حل کند؟

black بیشتر خطاهای تورفتگی را حل می‌کند، ولی در بعضی موارد مثل خطاهای منطقی تورفتگی (جایی که کد باید تو رفته باشد ولی نیست)، نمی‌تواند کمکی کند. در چنین مواردی، باید دستی ساختار را اصلاح کنید.

چگونه از این خطا در پروژه‌های تیمی پیشگیری کنم؟

سه رویکرد: اول، استفاده از pre-commit hook با black. دوم، تنظیم یکسان ویرایشگر در تمام تیم. سوم، استفاده از یک فایل .editorconfig که تنظیمات را برای همه‌ی ویرایشگرها یکسان می‌کند:

# .editorconfig
[*.py]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

تفاوت IndentationError و SyntaxError چیست؟

SyntaxError یک کلاس عمومی برای خطاهای نگارشی است. IndentationError یک زیرکلاس از SyntaxError است که به‌طور خاص برای خطاهای تورفتگی استفاده می‌شود. بنابراین هر IndentationError یک SyntaxError هم هست. جزئیات کامل در خطای SyntaxError در Python آمده است.

آیا در Jupyter Notebook هم این خطا رخ می‌دهد؟

بله، ولی به شکل متفاوت. در Jupyter، کد در سلول‌ها تقسیم می‌شود. اگر در یک سلول، تورفتگی ناقص باشد، خطا در زمان اجرای همان سلول رخ می‌دهد. تفاوت اصلی: در Jupyter، اگر سلول‌ها جداگانه اجرا شوند، خطای یک سلول، اجرای سلول‌های دیگر را متوقف نمی‌کند.

چگونه در Jupyter Notebook whitespace را ببینم؟

در Jupyter، به‌طور پیش‌فرض whitespace نمایش داده نمی‌شود. برای نمایش، باید یک افزونه یا تنظیم خاص اعمال کنید. راه ساده‌تر: کد را در یک ویرایشگر با نمایش whitespace باز کنید.

چرا این خطا در فایل‌های بزرگ‌تر بیشتر شایع است؟

چون در فایل‌های بزرگ، احتمال ترکیب Tab و Space یا اشتباه در تورفتگی بیشتر است. علاوه بر این، وقتی چند توسعه‌دهنده روی یک فایل کار می‌کنند، تنظیمات متفاوت می‌تواند این خطا را ایجاد کند. راه‌حل: استفاده از linter و formatter خودکار.

آیا PyCharm می‌تواند به‌طور خودکار IndentationError را رفع کند؟

بله، PyCharm گزینه‌ی «Reformat Code» دارد (Ctrl+Alt+L) که فایل را بازنویسی می‌کند. اگر تنظیمات code style به‌درستی تنظیم شده باشد، این گزینه بخش بزرگی از IndentationErrorها را حل می‌کند.

چگونه از این خطا در فایل‌های CSV/JSON که به‌عنوان کد Python استفاده می‌شوند پیشگیری کنم؟

فایل‌های داده‌ی خام مثل CSV و JSON، تورفتگی معنادار ندارند. اگر از این داده‌ها برای تولید کد Python استفاده می‌کنید (مثلاً template generation)، از ابزارهای استاندارد مثل black برای فرمت نهایی استفاده کنید.

آیا در Python 3، Tab معادل 4 Space است؟

نه دقیقاً. در Python 3، Tab معادل 8 Space در نظر گرفته می‌شود، نه 4. این تفاوت باعث می‌شود که اگر کد شما در ویرایشگری نوشته شده که Tab را به‌عنوان 4 Space نمایش می‌دهد، در اجرا به‌عنوان 8 Space محسوب شود و خطا بدهد.

آیا می‌توانم با دستور خط فرمان، whitespace را در فایل‌های Python پیدا کنم؟

بله، در Linux/Mac:

grep -nP "\t" *.py  # فایل‌هایی که Tab دارند

یا با ابزار flake8:

flake8 --select=W191,W291,W293 .

این کدها به‌طور خاص برای خطاهای whitespace تعریف شده‌اند.

چگونه در Python، تعداد space در یک خط را بشمارم؟

با استفاده از len() و lstrip():

line = "    x = 1"
indent = len(line) - len(line.lstrip())
print(indent)  # 4

این رویکرد در دیباگ کد کمک‌کننده است.

آیا خطای IndentationError روی performance تأثیر دارد؟

خود خطا در زمان parse رخ می‌دهد و اجرا را متوقف می‌کند. بنابراین این خطا، یک خطای «یا اجرا می‌شود یا نمی‌شود» است، نه یک مسئله‌ی performance. پس از رفع خطا، performance تحت تأثیر قرار نمی‌گیرد.

آیا در Cython یا Python compiled، این خطا رخ می‌دهد؟

بله، در Cython و Python compiled هم خطاهای تورفتگی ممکن است. تفاوت: در Cython، خطاها ممکن است در زمان compile تشخیص داده شوند، نه در زمان parse.

چگونه از این خطا در فایل‌هایی که از ابزارهای دیگر تولید می‌شوند پیشگیری کنم؟

اگر فایل‌های Python با ابزارهایی مثل template engine تولید می‌شوند، توصیه می‌شود قبل از استفاده، با black یا autopep8 بازفرمت شوند. این رویکرد، از بروز خطاهای ظریف پیشگیری می‌کند.

آیا خطای IndentationError در Python 2 و 3 متفاوت است؟

رفتار کلی مشابه است، ولی تفاوت در جزئیات. در Python 2، Tab معادل 8 Space بود. در Python 3، همین است ولی با سختگیری بیشتری ترکیب Tab و Space را رد می‌کند.

آیا استفاده از pre-commit در تیم، اجبار است یا اختیار؟

در پروژه‌های حرفه‌ای، pre-commit hook به‌عنوان ابزار اجبار توصیه می‌شود. در پروژه‌های شخصی، اختیاری است. در هر حال، وجود pre-commit باعث یکنواختی کد می‌شود و بخش بزرگی از خطاهای تورفتگی را پیشگیری می‌کند.

آیا می‌توانم با Git، فایل‌های Python را به‌طور خودکار فرمت کنم؟

بله، با ترکیب pre-commit و black. در فایل .pre-commit-config.yaml، black را تعریف می‌کنید و Git قبل از هر commit، فایل‌ها را بازفرمت می‌کند. اگر فرمت تغییری داشت، commit متوقف می‌شود و شما باید تغییرات را اضافه کنید. این رویکرد، یکنواختی کد را تضمین می‌کند.

چرا این خطا در کدهای تولید شده توسط AI بیشتر دیده می‌شود؟

کدهای تولید شده توسط ابزارهای AI می‌توانند به‌دلیل تفاوت در روش تولید، ترکیب Tab و Space یا تورفتگی نامنظم داشته باشند. راه‌حل: قبل از استفاده، کد را با black بازفرمت کنید. این رویکرد ساده، بسیاری از خطاهای AI تولیدشده را رفع می‌کند.

آنچه از سال‌ها کار با Python و تورفتگی آموختم

اگر بخواهم چکیده‌ی این سال‌ها را در چند جمله بگویم، سه اصل عملی دارم:

یک: تنظیمات ویرایشگر، سرمایه‌گذاری اولیه است. سرمایه‌گذاری ده دقیقه‌ای در تنظیم editorconfig و pre-commit، ساعت‌ها دیباگ آینده را حذف می‌کند. این تنظیم، یک‌بار انجام می‌شود و در تمام پروژه‌ها اعمال می‌شود.

دو: نمایش whitespace، عادت حرفه‌ای است. در پروژه‌های Python، نمایش whitespace را همیشه فعال نگه دارید. این کار، خطاهای تورفتگی را در لحظه‌ی وقوع نشان می‌دهد، نه در زمان parse.

سه: ابزارهای خودکار، بهترین دوست شما هستند. black، flake8، و ابزارهای مشابه، بخش بزرگی از خطاهای تورفتگی و سبک کد را پیشگیری می‌کنند. این ابزارها را در CI و pre-commit استفاده کنید.

در کنار این سه اصل، یک هشدار عملی هم دارم: خطای IndentationError در نگاه اول یک مشکل ساده به‌نظر می‌رسد، ولی در پروژه‌های تیمی، می‌تواند به یک منبع دائمی تنش تبدیل شود. ریشه، معمولاً تنظیمات متفاوت ویرایشگرها است. راه‌حل ریشه‌ای، استفاده از یک .editorconfig مشترک و یک pre-commit hook است که تنظیمات را در تمام تیم یکسان می‌کند.

خطای IndentationError در Python، در نگاه اول یک مانع به‌نظر می‌رسد، ولی در باطن، یک فرصت برای بهبود است. این خطا شما را وادار می‌کند که تنظیمات محیط را جدی بگیرید، ابزارهای خودکار را بشناسید، و با استانداردهای جامعه‌ی Python همراه شوید. اگر این سیگنال را جدی بگیرید، پروژه‌ی شما در ماه‌های بعد سریع‌تر، تمیزتر، و قابل نگهداری‌تر خواهد بود.

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

اگر خطای IndentationError در پروژه‌ی شما به شکلی ظاهر شده که با الگوهای این مقاله حل نشده، برای من جالب است بدانم کدام سناریو بود. تجربه‌ی خودتان را در دیدگاه‌ها بنویسید؛ به‌ویژه اگر راه‌حلی پیدا کرده‌اید که هنوز در این مقاله نیست. 📐