تازه‌های پایتون 2.3

نویسنده:

A.M. Kuchling

این مقاله قابلیت‌های جدید در پایتون 2.3 را توضیح می‌دهد. پایتون 2.3 در ۲۹ ژوئیه ۲۰۰۳ منتشر شد.

محورهای اصلی Python 2.3 عبارت‌اند از صیقل‌دادن برخی از قابلیت‌های افزوده‌شده در 2.2، افزودن بهبودهای گوناگونِ کوچک اما مفید به هسته زبان، و گسترش کتابخانه استاندارد. مدل شیء جدیدی که در نسخه پیشین معرفی شد، از ۱۸ ماه رفع اشکال و از تلاش‌های بهینه‌سازی که کارایی کلاس‌های سبک جدید (new-style) را بهبود بخشیده‌اند، بهره برده است. چند تابع توکار جدید مانند sum() و enumerate() افزوده‌شده‌اند. عملگر in اکنون می‌تواند برای جستجوی زیررشته‌ها به کار رود (مثلاً "ab" in "abc" مقدار True را برمی‌گرداند).

برخی از ویژگی‌های جدید فراوان کتابخانه عبارت‌اند از: انواع داده بولی، مجموعه، هیپ و تاریخ/زمان؛ توانایی ایمپورت کردن ماژول‌ها از آرشیوهای با قالب ZIP؛ پشتیبانی از فراداده برای کاتالوگ پایتون که مدت‌ها مورد انتظار بود؛ نسخه‌ی به‌روزشده‌ی IDLE؛ و ماژول‌هایی برای گزارش‌گیری پیام‌ها، شکستن سطرهای متن، تجزیه پرونده‌های CSV، پردازش گزینه‌های خط فرمان و استفاده از پایگاه‌های داده BerkeleyDB... فهرست ماژول‌های جدید و بهبودیافته طولانی است.

این مقاله نمی‌کوشد مشخصات کاملی از قابلیت‌های جدید ارائه دهد، بلکه در عوض مرور کلی مناسبی فراهم می‌کند. برای جزئیات کامل، باید به مستندات پایتون 2.3 مانند مرجع کتابخانه پایتون و راهنمای مرجع پایتون مراجعه کنید. اگر می‌خواهید پیاده‌سازی کامل و منطق طراحی را درک کنید، به PEP (پیشنهاد بهبود پایتون) مربوط به قابلیت جدید مورد نظر مراجعه کنید.

PEP 218: نوع داده مجموعه استاندارد

ماژول جدید sets شامل پیاده‌سازی یک نوع داده مجموعه است. کلاس Set برای مجموعه‌های تغییرپذیر است؛ مجموعه‌هایی که می‌توان به آن‌ها عضو افزود و از آن‌ها عضو حذف کرد. کلاس ImmutableSet برای مجموعه‌هایی است که نمی‌توان آن‌ها را تغییر داد، و در نتیجه می‌توان از نمونه‌های ImmutableSet به‌عنوان کلیدهای دیکشنری استفاده کرد. مجموعه‌ها بر پایه دیکشنری‌ها ساخته شده‌اند، بنابراین عناصر درون یک مجموعه باید هش‌پذیر باشند.

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

>>> import sets
>>> S = sets.Set([1,2,3])
>>> S
Set([1, 2, 3])
>>> 1 in S
True
>>> 0 in S
False
>>> S.add(5)
>>> S.remove(3)
>>> S
Set([1, 2, 5])
>>>

اجتماع و اشتراک مجموعه‌ها را می‌توان با متدهای union() و intersection() محاسبه کرد؛ در نمادگذاری جایگزین، از عملگرهای بیتی & و | استفاده می‌شود. مجموعه‌های تغییرپذیر نیز نسخه‌های درجای این متدها، یعنی union_update() و intersection_update() را دارند.

>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([4,5,6])
>>> S1.union(S2)
Set([1, 2, 3, 4, 5, 6])
>>> S1 | S2                  # Alternative notation
Set([1, 2, 3, 4, 5, 6])
>>> S1.intersection(S2)
Set([])
>>> S1 & S2                  # Alternative notation
Set([])
>>> S1.union_update(S2)
>>> S1
Set([1, 2, 3, 4, 5, 6])
>>>

همچنین می‌توان تفاضل متقارن دو مجموعه را گرفت. این، مجموعه‌ی همه‌ی المان‌هایی است که در اجتماع هستند اما در اشتراک نیستند. به بیان دیگر، تفاضل متقارن شامل همه‌ی المان‌هایی است که دقیقاً در یک مجموعه قرار دارند. باز هم یک نماد جایگزین (^) و نسخه‌ای درجا با نام نازیبای symmetric_difference_update() وجود دارد.

>>> S1 = sets.Set([1,2,3,4])
>>> S2 = sets.Set([3,4,5,6])
>>> S1.symmetric_difference(S2)
Set([1, 2, 5, 6])
>>> S1 ^ S2
Set([1, 2, 5, 6])
>>>

همچنین متدهای issubset() و issuperset() برای بررسی اینکه آیا یک مجموعه زیرمجموعه یا ابرمجموعه مجموعه‌ای دیگر است، وجود دارند:

>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([2,3])
>>> S2.issubset(S1)
True
>>> S1.issubset(S2)
False
>>> S1.issuperset(S2)
True
>>>

همچنین ملاحظه نمائید

PEP 218 - افزودن نوع شیء مجموعه توکار

PEP نوشته‌شده توسط Greg V. Wilson. پیاده‌سازی‌شده توسط Greg V. Wilson، Alex Martelli و GvR.

PEP 255: تولیدگرهای ساده

در پایتون 2.2، تولیدگرها به‌عنوان یک قابلیت اختیاری اضافه شدند که با دایرکتیو from __future__ import generators فعال می‌شدند. در نسخه 2.3 تولیدگرها دیگر نیازی به فعال‌سازی خاص ندارند و اکنون همیشه وجود دارند؛ این بدان معناست که yield اکنون همیشه یک کلیدواژه است. بقیه‌ی این بخش رونوشتی از توضیحات تولیدگرها در سند «چه چیزهایی در پایتون 2.2 جدید است» است؛ اگر آن را در زمان انتشار پایتون 2.2 خوانده‌اید، می‌توانید از خواندن بقیه‌ی این بخش صرف‌نظر کنید.

بی‌تردید با نحوه‌ی کارکرد فراخوانی توابع در پایتون یا C آشنا هستید. وقتی تابعی را فراخوانی می‌کنید، تابع یک فضای نام خصوصی می‌گیرد که متغیرهای محلی‌اش در آن ایجاد می‌شوند. وقتی تابع به دستور return می‌رسد، متغیرهای محلی نابود می‌شوند و مقدار حاصل به فراخوانی‌کننده بازگردانده می‌شود. فراخوانی بعدی همان تابع، مجموعه‌ای تازه از متغیرهای محلی دریافت خواهد کرد. اما اگر متغیرهای محلی هنگام خروج از تابع دور ریخته نمی‌شدند چه؟ اگر می‌توانستید بعداً تابع را از همان‌جایی که متوقف شده بود از سر بگیرید چه؟ این همان چیزی است که تولیدگرها فراهم می‌کنند؛ می‌توان آن‌ها را توابع قابل ازسرگیری در نظر گرفت.

این ساده‌ترین مثال یک تابع تولیدگر است:

def generate_ints(N):
    for i in range(N):
        yield i

کلیدواژه‌ی جدیدی، yield، برای تولیدگرها معرفی شد. هر تابعی که دستور yield را داشته باشد، یک تابع تولیدگر است؛ این موضوع توسط کامپایلر بایت‌کد پایتون تشخیص داده می‌شود که در نتیجه، تابع را به‌طور خاص کامپایل می‌کند.

وقتی یک تابع تولیدگر را فراخوانی می‌کنید، یک مقدار واحد برنمی‌گرداند؛ در عوض شیء تولیدگری را برمی‌گرداند که از پروتکل پیمایش‌گر پشتیبانی می‌کند. با اجرای دستور yield، تولیدگر مقدار i را خروجی می‌دهد، مشابه دستور return. تفاوت بزرگ بین yield و دستور return این است که با رسیدن به yield، وضعیت اجرای تولیدگر معلق می‌شود و متغیرهای محلی حفظ می‌شوند. در فراخوانی بعدی متد .next() تولیدگر، تابع بلافاصله پس از دستور yield به اجرا ادامه می‌دهد. (به دلایل پیچیده، دستور yield در بلوک try از دستور try...finally مجاز نیست؛ برای توضیح کامل تعامل بین yield و استثناها، PEP 255 را بخوانید.)

در ادامه، نمونه‌ای از استفاده از تولیدگر generate_ints() آمده است:

>>> gen = generate_ints(3)
>>> gen
<generator object at 0x8117f90>
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
2
>>> gen.next()
Traceback (most recent call last):
  File "stdin", line 1, in ?
  File "stdin", line 2, in generate_ints
StopIteration

شما می‌توانید به همان خوبی for i in generate_ints(5) بنویسید، یا a,b,c = generate_ints(3).

درون یک تابع تولیدگر، دستور return تنها می‌تواند بدون مقدار به کار رود و پایان دنباله مقادیر را نشان می‌دهد؛ پس از آن، تولیدگر نمی‌تواند مقادیر بیشتری را بازگرداند. return همراه با مقدار، مانند return 5، درون یک تابع تولیدگر خطای نحوی است. پایان نتایج تولیدگر را همچنین می‌توان با برافراختن دستی StopIteration، یا صرفاً با رها کردن جریان اجرا تا خروج از انتهای تابع، نشان داد.

شما می‌توانستید اثر تولیدگرها را به‌صورت دستی با نوشتن کلاس خودتان و ذخیره‌ی تمام متغیرهای محلی تولیدگر به‌عنوان متغیرهای نمونه به دست آورید. برای مثال، برای برگرداندن فهرستی از اعداد صحیح، می‌توان self.count را برابر ۰ قرار داد و کاری کرد که متد next() مقدار self.count را افزایش دهد و آن را برگرداند. با این حال، برای یک تولیدگر نسبتاً پیچیده، نوشتن کلاس متناظر بسیار شلوغ‌تر خواهد بود. Lib/test/test_generators.py شامل تعدادی مثال جالب‌تر است. ساده‌ترین آن‌ها پیمایش میان‌ترتیب (in-order) یک درخت را با استفاده از تولیدگرها به‌صورت بازگشتی پیاده‌سازی می‌کند.

# A recursive generator that generates Tree leaves in in-order.
def inorder(t):
    if t:
        for x in inorder(t.left):
            yield x
        yield t.label
        for x in inorder(t.right):
            yield x

دو مثال دیگر در Lib/test/test_generators.py راه‌حل‌هایی برای مسئله N وزیر (قرار دادن $N$ وزیر روی یک صفحه‌ی شطرنج $NxN$ به‌طوری که هیچ وزیری وزیر دیگری را تهدید نکند) و گردش اسب (Knight's Tour) (مسیری که اسب را به همه‌ی خانه‌های یک صفحه‌ی شطرنج $NxN$ می‌برد، بدون آنکه هیچ خانه‌ای دو بار بازدید شود) تولید می‌کنند.

ایده‌ی تولیدگرها از دیگر زبان‌های برنامه‌نویسی، به‌ویژه Icon (https://www2.cs.arizona.edu/icon/) که در آن ایده‌ی تولیدگرها نقشی محوری دارد، برآمده است. در Icon، هر عبارت و فراخوانی تابع مانند یک تولیدگر رفتار می‌کند. یک نمونه از «An Overview of the Icon Programming Language» در https://www2.cs.arizona.edu/icon/docs/ipd266.htm تصویری از چگونگی این موضوع ارائه می‌دهد:

sentence := "Store it in the neighboring harbor"
if (i := find("or", sentence)) > 5 then write(i)

در Icon تابع find() اندیس‌هایی را که زیررشته‌ی «or» در آن‌ها یافت می‌شود برمی‌گرداند: ۳، ۲۳، ۳۳. در دستور if، ابتدا مقدار ۳ به i انتساب داده می‌شود، اما ۳ کمتر از ۵ است، بنابراین مقایسه شکست می‌خورد و Icon آن را با مقدار دوم یعنی ۲۳ دوباره امتحان می‌کند. ۲۳ بزرگ‌تر از ۵ است، پس این بار مقایسه موفق می‌شود و کد مقدار ۲۳ را روی صفحه چاپ می‌کند.

پایتون در پذیرش تولیدگر‌ها به‌عنوان یک مفهوم مرکزی، به هیچ‌وجه به اندازه‌ی آیکون (Icon) پیش نمی‌رود. تولیدگر‌ها بخشی از هسته‌ی زبان پایتون محسوب می‌شوند، اما یادگیری یا استفاده از آن‌ها اجباری نیست؛ اگر هیچ‌یک از مسئله‌های شما را حل نمی‌کنند، می‌توانید با خیال راحت آن‌ها را نادیده بگیرید. یکی از ویژگی‌های نوآورانه‌ی رابط پایتون در مقایسه با رابط آیکون این است که وضعیت یک تولیدگر به‌صورت یک شیء عینی (پیمایش‌گر) نمایش داده می‌شود که می‌توان آن را به توابع دیگر پاس داد یا در یک ساختار داده ذخیره کرد.

همچنین ملاحظه نمائید

PEP 255 - تولیدگرهای ساده

نوشته Neil Schemenauer، Tim Peters و Magnus Lie Hetland. عمدتاً توسط Neil Schemenauer و Tim Peters پیاده‌سازی شده، همراه با اصلاحات دیگری از سوی گروه Python Labs.

PEP 263: کدگذاری‌های کد منبع

اکنون می‌توان اعلام کرد که پرونده‌های منبع پایتون با کدگذاری‌های مختلف مجموعه نویسه هستند. کدگذاری‌ها با گنجاندن یک کامنت با قالب‌بندی خاص در سطر اول یا دوم پرونده منبع اعلام می‌شوند. برای مثال، یک پرونده UTF-8 می‌تواند به این صورت اعلام شود:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

بدون چنین اعلان کدگذاری‌ای، کدگذاری پیش‌فرض استفاده‌شده اسکی ۷-بیتی است. اجرا یا ایمپورت کردن ماژول‌هایی که حاوی مقادیر لفظی رشته با نویسه‌های ۸-بیتی هستند و اعلان کدگذاری ندارند، منجر به صدور DeprecationWarning از سوی پایتون 2.3 خواهد شد؛ در 2.4 این یک خطای نحوی خواهد بود.

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

همچنین ملاحظه نمائید

PEP 263 - تعریف کدگذاری‌های کد منبع پایتون

نوشته‌شده توسط Marc-André Lemburg و Martin von Löwis؛ پیاده‌سازی‌شده توسط Suzuki Hisao و Martin von Löwis.

PEP 273: ایمپورت کردن ماژول‌ها از آرشیوهای ZIP

ماژول جدید zipimport پشتیبانی از ایمپورت کردن ماژول‌ها از یک آرشیو با فرمت ZIP را اضافه می‌کند. لازم نیست این ماژول را به‌صورت صریح ایمپورت کنید؛ اگر نام پرونده‌ی یک آرشیو ZIP به sys.path اضافه شود، این ماژول به‌طور خودکار ایمپورت خواهد شد. برای مثال:

amk@nyman:~/src/python$ unzip -l /tmp/example.zip
Archive:  /tmp/example.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
     8467  11-26-02 22:30   jwzthreading.py
 --------                   -------
     8467                   1 file
amk@nyman:~/src/python$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32)
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'
>>>

یک ورودی در sys.path اکنون می‌تواند نام پرونده‌ی یک آرشیو ZIP باشد. آرشیو ZIP می‌تواند هر نوع پرونده‌ای را در بر داشته باشد، اما تنها پرونده‌هایی با نام *.py، *.pyc یا *.pyo را می‌توان ایمپورت کرد. اگر یک آرشیو فقط شامل پرونده‌های *.py باشد، پایتون تلاش نمی‌کند با افزودن پرونده‌ی *.pyc متناظر، آرشیو را تغییر دهد؛ به این معنا که اگر یک آرشیو ZIP شامل پرونده‌های *.pyc نباشد، ایمپورت کردن ممکن است نسبتاً کند باشد.

همچنین می‌توان مسیری درون آرشیو را مشخص کرد تا فقط از یک زیرپوشه ایمپورت انجام شود؛ برای مثال، مسیر /tmp/example.zip/lib/ فقط از زیرپوشه‌ی lib/ درون آرشیو ایمپورت می‌کند.

همچنین ملاحظه نمائید

PEP 273 - ایمپورت ماژول‌ها از آرشیوهای Zip

نوشته‌شده توسط James C. Ahlstrom، که همچنین یک پیاده‌سازی نیز ارائه کرد. پایتون 2.3 از مشخصات PEP 273 پیروی می‌کند، اما از پیاده‌سازی‌ای استفاده می‌کند که توسط Just van Rossum نوشته شده و از قلاب‌های ایمپورت توصیف‌شده در PEP 302 استفاده می‌کند. برای توصیف قلاب‌های ایمپورت جدید، به بخش PEP 302: قلاب‌های جدید ایمپورت مراجعه کنید.

PEP 277: پشتیبانی از نام‌های پرونده‌ی یونیکد برای ویندوز NT

در ویندوز NT، 2000 و XP، سیستم نام‌های پرونده را به‌صورت رشته‌های یونیکد ذخیره می‌کند. به‌طور سنتی، پایتون نام‌های پرونده را به‌صورت رشته‌های بایتی نمایش داده است، که این کافی نیست، زیرا باعث می‌شود برخی از نام‌های پرونده در دسترس نباشند.

پایتون اکنون اجازه می‌دهد از رشته‌های یونیکد دلخواه (در چارچوب محدودیت‌های سامانه فایل‌بندی) برای تمام توابعی که نام پرونده‌ها را انتظار دارند استفاده کنید؛ به‌ویژه تابع توکار open(). اگر یک رشته یونیکد به os.listdir() داده شود، پایتون اکنون فهرستی از رشته‌های یونیکد برمی‌گرداند. تابع جدید os.getcwdu() پوشه‌ی جاری را به صورت یک رشته یونیکد برمی‌گرداند.

رشته‌های بایتی همچنان به‌عنوان نام پرونده‌ها کار می‌کنند و در ویندوز، پایتون آن‌ها را به‌طور شفاف با استفاده از کدگذاری mbcs به یونیکد تبدیل می‌کند.

سایر سیستم‌ها نیز اجازه می‌دهند از رشته‌های یونیکد به‌عنوان نام پرونده استفاده شود، اما این رشته‌ها را پیش از ارسال به سیستم، به رشته‌های بایتی تبدیل می‌کنند؛ این کار می‌تواند باعث پرتاب UnicodeError شود. برنامه‌ها می‌توانند با بررسی os.path.supports_unicode_filenames، که مقداری بولی است، آزمایش کنند که آیا رشته‌های یونیکد دلخواه به‌عنوان نام پرونده پشتیبانی می‌شوند یا خیر.

در مک‌اواس، os.listdir() اکنون ممکن است نام‌های پرونده‌ی یونیکد را برگرداند.

همچنین ملاحظه نمائید

PEP 277 - پشتیبانی از نام‌های پرونده‌ی یونیکد در ویندوز NT

نوشته‌شده توسط Neil Hodgson؛ پیاده‌سازی‌شده توسط Neil Hodgson، Martin von Löwis و Mark Hammond.

PEP 278: پشتیبانی از سطرهای جدید همگانی

سه سیستم‌عامل اصلی که امروزه استفاده می‌شوند عبارت‌اند از Microsoft Windows، سیستم‌عامل مکینتاش اپل، و مشتقات گوناگون یونیکس. یک آزار جزئی کار بین‌پلتفرمی این است که این سه پلتفرم همگی از نویسه‌های متفاوتی برای نشان‌گذاری انتهای سطرها در پرونده‌های متنی استفاده می‌کنند. یونیکس از تغذیه‌ی سطر (نویسه اسکی ۱۰)، مک‌اواس از بازگشت به ابتدای سطر (نویسه اسکی ۱۳)، و ویندوز از دنباله‌ی دو نویسه‌ای شامل بازگشت به ابتدای سطر به‌علاوه سطر جدید استفاده می‌کنند.

شیءهای پرونده پایتون اکنون می‌توانند از قراردادهای پایان سطر دیگری غیر از قرارداد پلتفرمی که پایتون روی آن در حال اجراست، پشتیبانی کنند. باز کردن یک پرونده با حالت 'U' یا 'rU'، آن را برای خواندن در حالت سطرهای جدید همگانی باز می‌کند. هر سه قرارداد پایان سطر در رشته‌هایی که توسط متدهای مختلف پرونده مانند read() و readline() برگردانده می‌شوند، به '\n' تبدیل خواهند شد.

پشتیبانی از سطرهای جدید همگانی همچنین هنگام ایمپورت کردن ماژول‌ها و هنگام اجرای یک پرونده با تابع execfile() استفاده می‌شود. این بدان معناست که می‌توان ماژول‌های پایتون را بدون نیاز به تبدیل انتهای سطرها بین هر سه سیستم‌عامل به اشتراک گذاشت.

این قابلیت را می‌توان هنگام کامپایل پایتون، با مشخص کردن سوئیچ --without-universal-newlines در زمان اجرای اسکریپت configure پایتون، غیرفعال کرد.

همچنین ملاحظه نمائید

PEP 278 - پشتیبانی از سطرهای جدید همگانی

نوشته و پیاده‌سازی‌شده توسط جک جانسن.

PEP 279: enumerate()

تابع توکار جدید، enumerate()، برخی حلقه‌ها را کمی واضح‌تر می‌کند. enumerate(thing) که در آن thing یا یک پیمایش‌گر است یا یک دنباله، پیمایش‌گری را برمی‌گرداند که (0, thing[0])، (1, thing[1])، (2, thing[2]) و به همین ترتیب را برمی‌گرداند.

یک اصطلاح رایج برای تغییر تک‌تک عناصر یک فهرست به این شکل است:

for i in range(len(L)):
    item = L[i]
    # ... compute some result based on item ...
    L[i] = result

می‌توان این را با استفاده از enumerate() به این صورت بازنویسی کرد:

for i, item in enumerate(L):
    # ... compute some result based on item ...
    L[i] = result

همچنین ملاحظه نمائید

PEP 279 - تابع توکار enumerate()

نوشته و پیاده‌سازی‌شده توسط Raymond D. Hettinger.

PEP 282: بسته‌ی logging

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

کلاس Logger اصلی‌ترین کلاس است. بیشتر کدهای برنامه با یک یا چند شیء Logger سروکار خواهند داشت که هر یک توسط زیرسیستم خاصی از برنامه استفاده می‌شود. هر Logger با یک نام شناسایی می‌شود و نام‌ها با استفاده از . به‌عنوان جداکننده‌ی اجزا در یک سلسله‌مراتب سازمان‌دهی می‌شوند. برای مثال، ممکن است نمونه‌هایی از Logger با نام‌های server، server.auth و server.network داشته باشید. دو نمونه‌ی اخیر در سلسله‌مراتب پایین‌تر از server قرار دارند. این بدان معناست که اگر سطح جزئیات server را افزایش دهید یا پیام‌های server را به هندلر دیگری هدایت کنید، این تغییرات بر رکوردهایی که در server.auth و server.network ثبت می‌شوند نیز اعمال خواهند شد. همچنین یک Logger ریشه وجود دارد که والد تمام گزارش‌گیرهای دیگر است.

برای استفاده‌های ساده، بسته‌ی logging شامل چند تابع کمکی است که همیشه از گزارش‌گیر ریشه استفاده می‌کنند:

import logging

logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')

این خروجی زیر را تولید می‌کند:

WARNING:root:Warning:config file server.conf not found
ERROR:root:Error occurred
CRITICAL:root:Critical error -- shutting down

در پیکربندی پیش‌فرض، پیام‌های اطلاعاتی و اشکال‌زدایی سرکوب می‌شوند و خروجی به خطای استاندارد ارسال می‌شود. شما می‌توانید نمایش پیام‌های اطلاعاتی و اشکال‌زدایی را با فراخوانی متد setLevel() بر روی گزارش‌گیر ریشه فعال کنید.

توجه کنید که فراخوانی warning() از عملگرهای قالب‌بندی رشته استفاده می‌کند؛ همه‌ی توابع مربوط به گزارش‌گیری پیام‌ها، آرگومان‌های (msg, arg1, arg2, ...) را می‌گیرند و رشته‌ی حاصل از msg % (arg1, arg2, ...) را ثبت می‌کنند.

تابع exception() نیز وجود دارد که آخرین ردگیری پشته را ثبت می‌کند. هر یک از توابع دیگر نیز در صورتی که مقدار درستی برای آرگومان کلیدواژه‌ای exc_info مشخص کنید، ردگیری پشته را ثبت می‌کنند.

def f():
    try:    1/0
    except: logging.exception('Problem recorded')

f()

این خروجی زیر را تولید می‌کند:

ERROR:root:Problem recorded
Traceback (most recent call last):
  File "t.py", line 6, in f
    1/0
ZeroDivisionError: integer division or modulo by zero

برنامه‌های کمی پیشرفته‌تر به‌جای گزارش‌گیر ریشه از گزارش‌گیر دیگری استفاده می‌کنند. تابع getLogger(name) برای به دست آوردن یک گزارش‌گیر مشخص به کار می‌رود و در صورتی که هنوز وجود نداشته باشد، آن را ایجاد می‌کند. getLogger(None) گزارش‌گیر ریشه را برمی‌گرداند.

log = logging.getLogger('server')
 ...
log.info('Listening on port %i', port)
 ...
log.critical('Disk full')
 ...

رکوردهای گزارش معمولاً به بالای سلسله‌مراتب منتشر می‌شوند، بنابراین پیامی که در server.auth ثبت می‌شود، توسط server و root نیز دیده می‌شود، اما یک Logger می‌تواند با تنظیم ویژگی propagate خود بر روی False از این کار جلوگیری کند.

کلاس‌های بیشتری نیز توسط بسته‌ی logging ارائه شده‌اند که می‌توان آن‌ها را سفارشی‌سازی کرد. وقتی از یک نمونه‌ی Logger خواسته شود پیامی را ثبت کند، یک نمونه‌ی LogRecord ایجاد می‌کند که به هر تعداد از نمونه‌های مختلف Handler ارسال می‌شود. گزارش‌گیرها و هندلرها همچنین می‌توانند فهرستی از فیلترهای پیوست‌شده داشته باشند، و هر فیلتر می‌تواند باعث شود نمونه‌ی LogRecord نادیده گرفته شود یا می‌تواند پیش از عبور دادن رکورد، آن را تغییر دهد. وقتی در نهایت خروجی گرفته می‌شوند، نمونه‌های LogRecord توسط کلاس Formatter به متن تبدیل می‌شوند. همه‌ی این کلاس‌ها را می‌توان با کلاس‌هایی که خودتان به‌طور اختصاصی نوشته‌اید جایگزین کرد.

با همه‌ی این قابلیت‌ها، بسته‌ی logging باید انعطاف‌پذیری کافی را حتی برای پیچیده‌ترین برنامه‌ها فراهم کند. این صرفاً یک مرور ناقص از قابلیت‌های آن است، بنابراین لطفاً برای همه‌ی جزئیات به مستندات مرجع بسته مراجعه کنید. خواندن PEP 282 نیز سودمند خواهد بود.

همچنین ملاحظه نمائید

PEP 282 - یک سامانه گزارش‌گیری

نوشته‌شده توسط Vinay Sajip و Trent Mick؛ پیاده‌سازی‌شده توسط Vinay Sajip.

PEP 285: یک نوع بولی

نوع بولی در پایتون 2.3 اضافه شد. دو ثابت جدید به ماژول __builtin__ اضافه شدند: True و False. (ثابت‌های True و False در پایتون 2.2.1 به توکارها اضافه شدند، اما نسخه‌های 2.2.1 آن‌ها صرفاً به مقادیر عدد صحیح 1 و 0 تنظیم شده‌اند و نوع متفاوتی نیستند.)

شیء نوع برای این نوع جدید bool نام دارد؛ سازنده‌ی آن هر مقدار پایتونی را می‌گیرد و آن را به True یا False تبدیل می‌کند.

>>> bool(1)
True
>>> bool(0)
False
>>> bool([])
False
>>> bool( (1,) )
True

بیشتر ماژول‌های کتابخانه استاندارد و توابع توکار تغییر داده شده‌اند تا مقادیر بولی برگردانند.

>>> obj = []
>>> hasattr(obj, 'append')
True
>>> isinstance(obj, list)
True
>>> isinstance(obj, tuple)
False

بولی‌های پایتون با هدف اصلی شفاف‌تر کردن کد اضافه شدند. برای مثال، اگر در حال خواندن یک تابع هستید و به دستور return 1 برمی‌خورید، ممکن است از خود بپرسید که 1 نشان‌دهنده‌ی یک مقدار درستی بولی، یک اندیس، یا ضریبی است که در مقداری دیگر ضرب می‌شود. اما اگر دستور return True باشد، معنای مقدار بازگشتی کاملاً واضح است.

بولی‌های پایتون برای بررسی سخت‌گیرانه نوع افزوده نشده‌اند. یک زبان بسیار سخت‌گیر مانند پاسکال همچنین شما را از انجام محاسبات با بولی‌ها بازمی‌داشت و ایجاب می‌کرد که عبارت درون یک دستور if همیشه به نتیجه‌ای بولی ارزیابی شود. پایتون تا این حد سخت‌گیر نیست و هرگز هم نخواهد بود، همان‌طور که PEP 285 صراحتاً می‌گوید. این بدان معناست که همچنان می‌توانید از هر عبارتی در یک دستور if استفاده کنید، حتی عبارت‌هایی که به یک فهرست یا تاپل یا شیء دلخواهی ارزیابی می‌شوند. نوع بولی زیرکلاسی از کلاس int است تا محاسبات با استفاده از بولی همچنان کار کند.

>>> True + 1
2
>>> False + 1
1
>>> False * 75
0
>>> True * 75
75

برای خلاصه‌کردن True و False در یک جمله: آن‌ها شیوه‌های جایگزین برای نوشتن مقادیر عدد صحیح ۱ و ۰ هستند و تنها تفاوت این است که str() و repr() به‌جای رشته‌های '1' و '0'، رشته‌های 'True' و 'False' را برمی‌گردانند.

همچنین ملاحظه نمائید

PEP 285 - افزودن نوع بولی

نوشته و پیاده‌سازی‌شده توسط GvR.

PEP 293: کال‌بک‌های مدیریت خطای کدک

هنگام کدگذاری یک رشته یونیکد به یک رشته بایتی، ممکن است با نویسه‌های کدگذاری‌ناپذیر مواجه شوید. تاکنون، پایتون اجازه داده است که پردازش خطا را به‌صورت «strict» (پرتاب UnicodeError)، «ignore» (نادیده گرفتن نویسه) یا «replace» (استفاده از علامت سؤال در رشته خروجی) مشخص کنید، که «strict» رفتار پیش‌فرض است. ممکن است مطلوب باشد که یک پردازش جایگزین برای چنین خطاهایی تعیین کنید، مانند درج ارجاع نویسه XML یا ارجاع موجودیت HTML در رشته تبدیل‌شده.

پایتون اکنون یک چارچوب انعطاف‌پذیر برای افزودن راهبردهای پردازش متفاوت دارد. هندلر‌های خطای جدید را می‌توان با codecs.register_error() افزود و سپس کدک‌ها می‌توانند با codecs.lookup_error() به هندلر خطا دسترسی داشته باشند. یک API معادل C برای کدک‌های نوشته‌شده به زبان C اضافه شده است. هندلر خطا اطلاعات وضعیت لازم مانند رشته‌ای که در حال تبدیل است، موقعیتی در رشته که خطا در آن تشخیص داده شده است، و کدگذاری مقصد را دریافت می‌کند. سپس هندلر می‌تواند یا یک استثنا ایجاد کند یا یک رشته‌ی جایگزین برگرداند.

دو هندلر خطای دیگر با استفاده از این چارچوب پیاده‌سازی شده‌اند: "backslashreplace" از نقل‌قول بک‌اسلشی پایتون برای نمایش نویسه‌های کدگذاری‌ناپذیر استفاده می‌کند و "xmlcharrefreplace" ارجاع‌های نویسه XML تولید می‌کند.

همچنین ملاحظه نمائید

PEP 293 — کال‌بک‌های مدیریت خطای کدک

نوشته و پیاده‌سازی‌شده توسط Walter Dörwald.

PEP 301: اندیس بسته و فراداده برای Distutils

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

قلب کاتالوگ، دستور جدید register در Distutils است. اجرای python setup.py register فراداده‌های توصیف‌کننده‌ی یک بسته — مانند نام، نسخه، نگهدارنده، توضیحات و غیره — را جمع‌آوری کرده و آن‌ها را به یک سرور کاتالوگ مرکزی ارسال می‌کند. کاتالوگ حاصل از طریق https://pypi.org در دسترس است.

برای اینکه کاتالوگ کمی مفیدتر باشد، آرگومان کلیدواژه‌ای اختیاری جدید classifiers به تابع setup() در Distutils افزوده شده است. می‌توان فهرستی از رشته‌های به سبک Trove را برای کمک به دسته‌بندی نرم‌افزار ارائه کرد.

در اینجا نمونه‌ای از setup.py همراه با دسته‌بندی‌ها (classifiers) آمده است که به‌گونه‌ای نوشته شده است تا با نسخه‌های قدیمی‌تر Distutils سازگار باشد:

from distutils import core
kw = {'name': "Quixote",
      'version': "0.5.1",
      'description': "A highly Pythonic Web application framework",
      # ...
      }

if (hasattr(core, 'setup_keywords') and
    'classifiers' in core.setup_keywords):
    kw['classifiers'] = \
        ['Topic :: Internet :: WWW/HTTP :: Dynamic Content',
         'Environment :: No Input/Output (Daemon)',
         'Intended Audience :: Developers'],

core.setup(**kw)

فهرست کامل طبقه‌بندها را می‌توان با اجرای python setup.py register --list-classifiers به دست آورد.

همچنین ملاحظه نمائید

PEP 301 - اندیس بسته‌ها و فراداده برای Distutils

نوشته و پیاده‌سازی‌شده توسط ریچارد جونز.

PEP 302: قلاب‌های جدید ایمپورت

هرچند از زمانی که ماژول ihooks در پایتون 1.3 معرفی شد، نوشتن قلاب‌های ایمپورت سفارشی ممکن بوده است، اما هیچ‌کس هرگز واقعاً از آن خشنود نبوده است، زیرا نوشتن قلاب‌های ایمپورت جدید دشوار و درهم‌وبرهم است. جایگزین‌های پیشنهادی گوناگونی مانند ماژول‌های imputil و iu وجود داشته‌اند، اما هیچ‌کدام هرگز پذیرش زیادی کسب نکرده‌اند و هیچ‌کدام نیز به‌سادگی از کد C قابل استفاده نبودند.

PEP 302 ایده‌های خود را از پیشینیانش وام می‌گیرد، به‌ویژه از ماژول iu گوردون مک‌میلان. سه آیتم جدید به ماژول sys اضافه می‌شوند:

  • sys.path_hooks فهرستی از اشیاء فراخوانی‌پذیر است؛ این اشیاء اغلب اوقات کلاس‌ها هستند. هر شیء فراخوانی‌پذیر رشته‌ای حاوی مسیر را می‌گیرد و یا یک شیء ایمپورت‌کننده (importer) برمی‌گرداند که ایمپورت‌های مربوط به این مسیر را مدیریت خواهد کرد، یا اگر نتواند این مسیر را مدیریت کند، استثنای ImportError را ایجاد می‌کند.

  • sys.path_importer_cache شیءهای ایمپورت‌کننده را برای هر مسیر در نهانگاه نگه می‌دارد، بنابراین sys.path_hooks تنها یک بار برای هر مسیر نیاز به پیمایش خواهد داشت.

  • sys.meta_path فهرستی از اشیاء ایمپورت‌کننده (importer) است که پیش از بررسی sys.path پیمایش می‌شوند. این فهرست در ابتدا خالی است، اما کد کاربر می‌تواند اشیایی به آن اضافه کند. ماژول‌های توکار و فریزشده بیشتری می‌توانند توسط شیء افزوده‌شده به این فهرست ایمپورت شوند.

اشیاء ایمپورت‌کننده (importer) باید تنها یک متد داشته باشند، find_module(fullname, path=None). fullname نام یک ماژول یا بسته خواهد بود، مثلاً string یا distutils.core. find_module() باید یک شیء بارگذار بازگرداند که تنها یک متد، load_module(fullname)، دارد؛ این متد شیء ماژول مربوطه را ایجاد کرده و بازمی‌گرداند.

بنابراین، شبه‌کد منطق ایمپورت جدید پایتون چیزی شبیه به این است (کمی ساده‌سازی‌شده؛ برای جزئیات کامل به PEP 302 مراجعه کنید):

for mp in sys.meta_path:
    loader = mp(fullname)
    if loader is not None:
        <module> = loader.load_module(fullname)

for path in sys.path:
    for hook in sys.path_hooks:
        try:
            importer = hook(path)
        except ImportError:
            # ImportError, so try the other path hooks
            pass
        else:
            loader = importer.find_module(fullname)
            <module> = loader.load_module(fullname)

# Not found!
raise ImportError

همچنین ملاحظه نمائید

PEP 302 - قلاب‌های ایمپورت جدید

نوشته‌شده توسط Just van Rossum و Paul Moore. پیاده‌سازی‌شده توسط Just van Rossum.

PEP 305: پرونده‌های جداشده با ویرگول

پرونده‌های جدا‌شده با کاما قالبی پرکاربرد برای اکسپورت داده‌ها از پایگاه‌های داده و صفحه‌گسترده‌ها هستند. پایتون 2.3 پارسری برای پرونده‌های جدا‌شده با کاما می‌افزاید.

قالب جداشده با کاما در نگاه اول به‌طرزی فریبنده ساده به نظر می‌رسد:

هزینه ها,150,200,3.95

یک سطر را بخوانید و line.split(',') را فراخوانی کنید: چه چیزی می‌تواند ساده‌تر از این باشد؟ اما وقتی داده‌ی رشته‌ای که می‌تواند شامل کاما باشد را به میان بیاورید، اوضاع پیچیده‌تر می‌شود:

"هزینه ها",150,200,3.95,"شامل مالیات، هزینه ارسال و اقلام متفرقه"

یک عبارت باقاعده‌ی بزرگ و زشت می‌تواند این را پارس کند، اما استفاده از بسته‌ی جدید csv بسیار ساده‌تر است:

import csv

input = open('datafile', 'rb')
reader = csv.reader(input)
for line in reader:
    print line

تابع reader() تعدادی گزینه‌ی مختلف می‌پذیرد. جداکننده فیلد به ویرگول محدود نیست و می‌توان آن را به هر نویسه‌ای تغییر داد؛ نویسه‌های نقل‌قول و پایان سطر نیز به همین ترتیب قابل تغییر هستند.

می‌توان گویش‌های مختلفی از پرونده‌های جداشده با ویرگول را تعریف و ثبت کرد؛ در حال حاضر دو گویش وجود دارد که هر دو توسط Microsoft Excel استفاده می‌شوند. کلاس جداگانه‌ی csv.writer از دنباله‌ای از تاپل‌ها یا فهرست‌ها پرونده‌های جداشده با ویرگول تولید می‌کند و رشته‌هایی را که شامل جداکننده هستند، داخل نقل‌قول قرار می‌دهد.

همچنین ملاحظه نمائید

PEP 305 - API پرونده CSV

نوشته و پیاده‌سازی‌شده توسط Kevin Altis، Dave Cole، Andrew McNamara، Skip Montanaro و Cliff Wells.

PEP 307: بهبودهای پیکل

ماژول‌های pickle و cPickle در طول چرخه توسعه 2.3 مورد توجه قرار گرفتند. در نسخه 2.2، کلاس‌های سبک جدید می‌توانستند بدون دشواری پیکل شوند، اما به‌طور چندان فشرده‌ای پیکل نمی‌شدند؛ PEP 307 مثالی ساده را نقل می‌کند که در آن یک کلاس سبک جدید به رشته‌ی پیکل‌شده‌ای سه برابر طولانی‌تر از رشته‌ی مربوط به یک کلاس کلاسیک منجر می‌شود.

راه‌حل، ابداع یک پروتکل پیکل جدید بود. تابع pickle.dumps() مدت‌هاست که از یک پرچم متنی یا دودویی پشتیبانی می‌کند. در نسخه 2.3، این پرچم از یک مقدار بولی به یک عدد صحیح بازتعریف می‌شود: 0 قالب پیکل قدیمی حالت متنی است، 1 قالب دودویی قدیمی است، و اکنون 2 یک قالب جدید مخصوص نسخه 2.3 است. از یک ثابت جدید به نام pickle.HIGHEST_PROTOCOL می‌توان برای انتخاب پیشرفته‌ترین پروتکل موجود استفاده کرد.

پیکل‌گشایی دیگر یک عملیات ایمن تلقی نمی‌شود. pickle نسخه 2.2 قلاب‌هایی برای تلاش در جلوگیری از پیکل‌گشایی کلاس‌های ناامن فراهم می‌کرد (به‌طور خاص، ویژگی __safe_for_unpickling__)، اما هیچ‌یک از این کدها هرگز حسابرسی نشد و بنابراین همه‌ی آن‌ها در نسخه 2.3 به‌کلی حذف شده‌اند. شما نباید در هیچ نسخه‌ای از پایتون داده‌های غیرقابل اعتماد را پیکل‌گشایی کنید.

برای کاهش سربار پیکل‌سازی در کلاس‌های سبک جدید، رابط جدیدی برای سفارشی‌سازی پیکل‌سازی با استفاده از سه متد ویژه اضافه شد: __getstate__()، __setstate__() و __getnewargs__(). برای معناشناسی کامل این متدها به PEP 307 مراجعه کنید.

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

همچنین ملاحظه نمائید

PEP 307 - توسعه‌های پروتکل پیکل

نوشته و پیاده‌سازی‌شده توسط Guido van Rossum و Tim Peters.

اسلایس‌های توسعه‌یافته

از پایتون 1.4 به بعد، سینتکس اسلایس از یک آرگومان سوم اختیاری به نام «گام» یا «طول گام» پشتیبانی می‌کند. برای مثال، همه این‌ها سینتکس معتبر پایتون هستند: L[1:10:2]، L[:-1:1]، L[::-1]. این قابلیت به درخواست توسعه‌دهندگان Numerical Python — که به‌طور گسترده از آرگومان سوم استفاده می‌کند — به پایتون اضافه شد. با این حال، نوع‌های دنباله‌ای توکار فهرست، تاپل و رشته‌ی پایتون هرگز از این قابلیت پشتیبانی نکرده‌اند و اگر آن را امتحان می‌کردید، TypeError ایجاد می‌شد. مایکل هادسون وصلی برای رفع این کاستی ارائه کرد.

برای مثال، اکنون می‌توانید به‌سادگی المان‌هایی از یک فهرست را که اندیس‌های زوج دارند استخراج کنید:

>>> L = range(10)
>>> L[::2]
[0, 2, 4, 6, 8]

مقادیر منفی نیز برای ساختن کپی‌ای از همان فهرست به ترتیب معکوس کار می‌کنند:

>>> L[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

این برای تاپل‌ها، آرایه‌ها و رشته‌ها نیز کار می‌کند:

>>> s='abcd'
>>> s[::2]
'ac'
>>> s[::-1]
'dcba'

اگر دنباله‌ای تغییرپذیر مانند فهرست یا آرایه داشته باشید، می‌توانید به یک اسلایس توسعه‌یافته انتساب دهید یا آن را حذف کنید، اما تفاوت‌هایی بین انتساب به اسلایس‌های توسعه‌یافته و معمولی وجود دارد. از انتساب به اسلایس معمولی می‌توان برای تغییر طول دنباله استفاده کرد:

>>> a = range(3)
>>> a
[0, 1, 2]
>>> a[1:3] = [4, 5, 6]
>>> a
[0, 4, 5, 6]

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

>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> a[::2] = [0, -1]
>>> a
[0, 1, -1, 3]
>>> a[::2] = [0,1,2]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: attempt to assign sequence of size 3 to extended slice of size 2

حذف سرراست‌تر است:

>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> del a[::2]
>>> a
[1, 3]

اکنون می‌توانید اشیاء اسلایس را نیز به متدهای __getitem__() دنباله‌های توکار ارسال کنید:

>>> range(10).__getitem__(slice(0, 5, 2))
[0, 2, 4]

یا از اشیاء اسلایس مستقیماً در زیرنویس‌ها استفاده کنید:

>>> range(10)[slice(0, 5, 2)]
[0, 2, 4]

برای ساده‌سازی پیاده‌سازی دنباله‌هایی که از اسلایس‌بندی توسعه‌یافته پشتیبانی می‌کنند، اشیای اسلایس اکنون متدی به نام indices(length) دارند که با دریافت طول یک دنباله، تاپلی (start, stop, step) برمی‌گرداند که می‌توان آن را مستقیماً به range() ارسال کرد. indices() اندیس‌های حذف‌شده و خارج از محدوده را به شکلی سازگار با اسلایس‌های معمولی مدیریت می‌کند (و این عبارت بی‌ضرر، انبوهی از جزئیات گیج‌کننده را پنهان می‌کند!). این متد قرار است به این صورت استفاده شود:

class FakeSeq:
    ...
    def calc_item(self, i):
        ...
    def __getitem__(self, item):
        if isinstance(item, slice):
            indices = item.indices(len(self))
            return FakeSeq([self.calc_item(i) for i in range(*indices)])
        else:
            return self.calc_item(i)

از این مثال همچنین می‌توانید ببینید که شیء توکار slice اکنون شیء نوع برای نوع اسلایس است و دیگر یک تابع نیست. این امر با پایتون 2.2 سازگار است که در آن int، str و غیره دچار همین تغییر شدند.

سایر تغییرات زبان

در اینجا تمام تغییراتی که پایتون 2.3 در هسته‌ی زبان پایتون ایجاد می‌کند، آمده‌اند.

  • دستور yield اکنون همیشه یک کلیدواژه است، همان‌طور که در بخش PEP 255: تولیدگرهای ساده از این سند شرح داده شده است.

  • تابع توکار جدید enumerate() افزوده شد، همان‌طور که در بخش PEP 279: enumerate() این سند شرح داده شده است.

  • دو ثابت جدید، True و False، به همراه نوع توکار bool افزوده شدند، همان‌طور که در بخش PEP 285: یک نوع بولی این سند توضیح داده شده است.

  • سازنده نوع int() اکنون هنگامی که یک رشته یا عدد ممیز شناور برای جای‌گرفتن در یک عدد صحیح بیش از حد بزرگ باشد، به جای ایجاد OverflowError یک عدد صحیح بلند (long integer) برمی‌گرداند. این می‌تواند به نتیجه‌ای متناقض منجر شود که isinstance(int(expression), int) نادرست باشد، اما به نظر نمی‌رسد که این موضوع در عمل مشکلی ایجاد کند.

  • نوع‌های توکار اکنون از سینتکس اسلایس‌دهی توسعه‌یافته پشتیبانی می‌کنند، همان‌طور که در بخش اسلایس‌های توسعه‌یافته این سند توضیح داده شده است.

  • یک تابع توکار جدید، sum(iterable, start=0)، آیتم‌های عددی در شیء پیمایش‌پذیر را جمع می‌کند و مجموع آن‌ها را برمی‌گرداند. sum() فقط اعداد را می‌پذیرد، به این معنا که نمی‌توانید از آن برای الحاق تعدادی رشته استفاده کنید. (مشارکت‌شده توسط الکس مارتلی.)

  • list.insert(pos, value) زمانی که pos منفی بود، value را در ابتدای فهرست درج می‌کرد. این رفتار اکنون تغییر کرده است تا با اندیس‌گذاری اسلایس سازگار باشد؛ بنابراین وقتی pos برابر -1 باشد، value پیش از آخرین عنصر درج خواهد شد و به همین ترتیب.

  • list.index(value) که value را درون فهرست جستجو می‌کند و اندیس آن را برمی‌گرداند، اکنون آرگومان‌های اختیاری start و stop را می‌پذیرد تا جستجو را تنها به بخشی از فهرست محدود کند.

  • دیکشنری‌ها متد جدیدی به نام pop(key[, *default*]) دارند که مقدار متناظر با key را برمی‌گرداند و آن جفت کلید/مقدار را از دیکشنری حذف می‌کند. اگر کلید درخواستی در دیکشنری موجود نباشد، در صورت تعیین default، آن بازگردانده می‌شود و در غیر این صورت استثنای KeyError ایجاد می‌شود.

    >>> d = {1:2}
    >>> d
    {1: 2}
    >>> d.pop(4)
    Traceback (most recent call last):
      File "stdin", line 1, in ?
    KeyError: 4
    >>> d.pop(1)
    2
    >>> d.pop(1)
    Traceback (most recent call last):
      File "stdin", line 1, in ?
    KeyError: 'pop(): dictionary is empty'
    >>> d
    {}
    >>>
    

    یک متد کلاس جدید نیز وجود دارد، dict.fromkeys(iterable, value)، که دیکشنری‌ای می‌سازد که کلیدهای آن از پیمایش‌گر iterable ارائه‌شده گرفته شده‌اند و همه‌ی مقادیر آن برابر value تنظیم می‌شوند که مقدار پیش‌فرض آن None است.

    (وصله‌های ارائه‌شده توسط ریموند هتینگر.)

    همچنین، سازنده‌ی dict() اکنون آرگومان‌های کلیدواژه‌ای را برای ساده‌سازی ایجاد دیکشنری‌های کوچک می‌پذیرد:

    >>> dict(red=1, blue=2, green=3, black=4)
    {'blue': 2, 'black': 4, 'green': 3, 'red': 1}
    

    (با مشارکت Just van Rossum.)

  • دستور assert دیگر پرچم __debug__ را بررسی نمی‌کند، بنابراین دیگر نمی‌توانید ادعاها را با انتساب به __debug__ غیرفعال کنید. اجرای پایتون با سوئیچ -O همچنان کدی تولید می‌کند که هیچ ادعایی را اجرا نمی‌کند.

  • بیشتر اشیاء نوع اکنون فراخوانی‌پذیر هستند، بنابراین می‌توانید از آن‌ها برای ایجاد اشیاء جدیدی مانند توابع، کلاس‌ها و ماژول‌ها استفاده کنید. (این بدان معناست که ماژول new می‌تواند در یک نسخه‌ی آینده‌ی پایتون منسوخ شود، زیرا اکنون می‌توانید از اشیاء نوع موجود در ماژول types استفاده کنید.) برای مثال، می‌توانید با کد زیر یک شیء ماژول جدید ایجاد کنید:

    >>> import types
    >>> m = types.ModuleType('abc','docstring')
    >>> m
    <module 'abc' (built-in)>
    >>> m.__doc__
    'docstring'
    
  • هشدار جدیدی با نام PendingDeprecationWarning اضافه شد تا ویژگی‌هایی را که در حال منسوخ شدن هستند نشان دهد. این هشدار به‌صورت پیش‌فرض چاپ نخواهد شد. برای بررسی استفاده از ویژگی‌هایی که در آینده منسوخ خواهند شد، گزینه‌ی -Walways::PendingDeprecationWarning:: را در خط فرمان ارائه دهید یا از warnings.filterwarnings() استفاده کنید.

  • فرایند منسوخ‌سازی استثناهای مبتنی بر رشته، مانند raise "Error occurred"، آغاز شده است. raise کردن یک رشته اکنون PendingDeprecationWarning را فعال می‌کند.

  • استفاده از None به‌عنوان نام یک متغیر اکنون منجر به هشدار SyntaxWarning خواهد شد. در یک نسخه‌ی آینده از پایتون، None ممکن است سرانجام به یک کلیدواژه تبدیل شود.

  • متد xreadlines() اشیای پرونده، که در پایتون 2.1 معرفی شد، دیگر لازم نیست زیرا پرونده‌ها اکنون به‌عنوان پیمایش‌گر خود رفتار می‌کنند. xreadlines() در اصل به‌عنوان راهی سریع‌تر برای حلقه زدن روی تمام سطرهای یک پرونده معرفی شد، اما اکنون می‌توانید به‌سادگی بنویسید for line in file_obj. اشیای پرونده همچنین یک ویژگی جدید فقط‌خواندنی encoding دارند که کدگذاری مورد استفاده‌ی پرونده را نشان می‌دهد؛ رشته‌های یونیکد که در پرونده نوشته می‌شوند، به‌طور خودکار با استفاده از کدگذاری داده‌شده به بایت تبدیل می‌شوند.

  • ترتیب حل متدی که توسط کلاس‌های نو (new-style) استفاده می‌شود، تغییر کرده است، هرچند تفاوت را تنها زمانی متوجه خواهید شد که سلسله‌مراتب وراثت واقعاً پیچیده‌ای داشته باشید. کلاس‌های کلاسیک از این تغییر متأثر نمی‌شوند. پایتون 2.2 در ابتدا از مرتب‌سازی توپولوژیک نیاکان یک کلاس استفاده می‌کرد، اما نسخه‌ی 2.3 اکنون از الگوریتم C3 استفاده می‌کند که در مقاله‌ی "A Monotonic Superclass Linearization for Dylan" توصیف شده است. برای درک انگیزه‌ی این تغییر، مقاله‌ی میکله سیمیناتو ترتیب حل متد در پایتون 2.3 را بخوانید، یا بحث در python-dev را که با پیام موجود در https://mail.python.org/pipermail/python-dev/2002-October/029035.html آغاز می‌شود، بخوانید. ساموئله پدرونی نخستین بار به این مشکل اشاره کرد و همچنین با کدنویسی الگوریتم C3، راه‌حل آن را پیاده‌سازی کرد.

  • پایتون برنامه‌های چندنخی را با تعویض بین نخ‌ها پس از اجرای N بایت‌کد اجرا می‌کند. مقدار پیش‌فرض N از ۱۰ به ۱۰۰ بایت‌کد افزایش یافته است که با کاهش سربار تعویض، سرعت برنامه‌های تک‌نخی را افزایش می‌دهد. برخی برنامه‌های چندنخی ممکن است زمان پاسخ کندتری داشته باشند، اما این مشکل به‌سادگی با تنظیم مجدد محدودیت به عددی پایین‌تر با استفاده از sys.setcheckinterval(N) برطرف می‌شود. این محدودیت را می‌توان با تابع جدید sys.getcheckinterval() بازیابی کرد.

  • یک تغییر کوچک اما با آثار گسترده این است که نام نوع‌های توسعه‌ای که توسط ماژول‌های همراه پایتون تعریف می‌شوند، اکنون نام ماژول و یک '.' را پیش از نام نوع در بر دارند. برای مثال، در پایتون 2.2، اگر یک سوکت می‌ساختید و __class__ آن را چاپ می‌کردید، این خروجی را دریافت می‌کردید:

    >>> s = socket.socket()
    >>> s.__class__
    <type 'socket'>
    

    در 2.3، این را به دست می‌آورید:

    >>> s.__class__
    <type '_socket.socket'>
    
  • یکی از ناسازگاری‌های ذکرشده میان کلاس‌های سبک قدیمی و سبک جدید حذف شده است: اکنون می‌توانید به ویژگی‌های __name__ و __bases__ کلاس‌های سبک جدید مقدار اختصاص دهید. محدودیت‌هایی نیز بر آنچه می‌توان به __bases__ اختصاص داد وجود دارد که مشابه محدودیت‌های مربوط به انتساب به ویژگی __class__ یک نمونه است.

تغییرات رشته‌ها

  • عملگر in اکنون برای رشته‌ها به شکل متفاوتی کار می‌کند. پیش‌تر، هنگام ارزیابی X in Y که در آن X و Y رشته هستند، X تنها می‌توانست یک نویسه باشد. اکنون این وضعیت تغییر کرده است؛ X می‌تواند رشته‌ای با هر طولی باشد، و X in Y در صورتی که X زیررشته‌ای از Y باشد، True را برمی‌گرداند. اگر X رشته خالی باشد، نتیجه همیشه True است.

    >>> 'ab' in 'abcd'
    True
    >>> 'ad' in 'abcd'
    False
    >>> '' in 'abcd'
    True
    

    توجه داشته باشید که این به شما نمی‌گوید زیررشته از کجا شروع می‌شود؛ اگر به این اطلاعات نیاز دارید، از متد رشته‌ی find() استفاده کنید.

  • متدهای رشته‌ای strip()، lstrip() و rstrip() اکنون آرگومانی اختیاری برای مشخص کردن نویسه‌هایی که باید حذف شوند دارند. پیش‌فرض همچنان حذف تمام نویسه‌های فضای سفید است:

    >>> '   abc '.strip()
    'abc'
    >>> '><><abc<><><>'.strip('<>')
    'abc'
    >>> '><><abc<><><>\n'.strip('<>')
    'abc<><><>\n'
    >>> u'\u4000\u4001abc\u4000'.strip(u'\u4000')
    u'\u4001abc'
    >>>
    

    (پیشنهادشده توسط Simon Brunning و پیاده‌سازی‌شده توسط Walter Dörwald.)

  • متدهای رشته startswith() و endswith() اکنون اعداد منفی را برای پارامترهای start و end می‌پذیرند.

  • متد رشته‌ای جدید دیگری zfill() است که در اصل تابعی در ماژول string بود. zfill() یک رشته عددی را از سمت چپ با صفر پر می‌کند تا به عرض مشخص‌شده برسد. توجه داشته باشید که عملگر % همچنان انعطاف‌پذیرتر و قدرتمندتر از zfill() است.

    >>> '45'.zfill(4)
    '0045'
    >>> '12345'.zfill(4)
    '12345'
    >>> 'goofy'.zfill(6)
    '0goofy'
    

    (مشارکت‌کننده: والتر دوروالد.)

  • یک شیء نوع جدید، basestring، اضافه‌شده است. هم رشته‌های ۸-بیتی و هم رشته‌های یونیکد از این نوع ارث‌بری می‌کنند، بنابراین isinstance(obj, basestring) برای هر دو نوع رشته True را برمی‌گرداند. این یک نوع کاملاً انتزاعی است، بنابراین نمی‌توانید نمونه‌ای از basestring ایجاد کنید.

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

بهینه‌سازی‌ها

  • ایجاد نمونه‌های کلاس‌های سبک جدید بسیار سریع‌تر شده است؛ اکنون از کلاس‌های کلاسیک سریع‌تر هستند!

  • متد sort() از اشیای فهرست توسط تیم پیترز به‌طور گسترده بازنویسی شده است و پیاده‌سازی آن به‌طور چشمگیری سریع‌تر است.

  • ضرب اعداد صحیح بلند بزرگ اکنون به لطف پیاده‌سازی ضرب کاراتسوبا (Karatsuba) بسیار سریع‌تر شده است؛ الگوریتمی که مقیاس‌پذیری بهتری نسبت به O(n2) مورد نیاز برای الگوریتم ضرب دبستانی دارد. (وصل اصلی توسط Christopher A. Craig، و به‌طور قابل توجهی توسط Tim Peters بازنویسی شد.)

  • آپ‌کد SET_LINENO اکنون حذف شده است. این ممکن است بسته به ویژگی‌های خاص کامپایلر شما، افزایش کوچکی در سرعت فراهم کند. برای توضیح مفصل‌تر، به بخش سایر تغییرات و رفع اشکالات مراجعه کنید. (حذف‌شده توسط مایکل هادسون.)

  • اشیای xrange() اکنون پیمایش‌گر اختصاصی خود را دارند که باعث می‌شود for i in xrange(n) کمی سریع‌تر از for i in range(n) باشد. (وصل توسط Raymond Hettinger.)

  • تعدادی بازآرایی کوچک در نقاط داغ (hotspot) مختلف برای بهبود کارایی انجام شده است، مانند درون‌خطی کردن (inlining) یک تابع یا حذف بخشی از کد. (بیشتر توسط GvR پیاده‌سازی شده است، اما افراد زیادی تغییرات منفردی ارائه کرده‌اند.)

نتیجه نهایی بهینه‌سازی‌های نسخه 2.3 این است که پایتون 2.3 بنچمارک pystone را حدود ۲۵٪ سریع‌تر از پایتون 2.2 اجرا می‌کند.

ماژول‌های جدید، بهبودیافته و منسوخ

طبق معمول، کتابخانه استاندارد پایتون تعدادی بهبود و رفع اشکال دریافت کرد. در ادامه، فهرست ناقصی از قابل‌توجه‌ترین تغییرات که به ترتیب الفبایی بر اساس نام ماژول مرتب شده‌اند، آمده است. برای فهرست کامل‌تری از تغییرات، به پرونده‌ی Misc/NEWS در درخت منبع مراجعه کنید، یا برای همه‌ی جزئیات، گزارش‌های CVS را مرور کنید.

  • ماژول array اکنون از آرایه‌های نویسه‌های یونیکد با استفاده از نویسه‌ی قالب 'u' پشتیبانی می‌کند. آرایه‌ها همچنین اکنون از استفاده از عملگر انتساب += برای افزودن محتوای آرایه‌ی دیگر، و عملگر انتساب *= برای تکرار یک آرایه پشتیبانی می‌کنند. (مشارکت‌شده توسط جیسون اورندورف.)

  • ماژول bsddb توسط نسخه 4.1.6 از بسته PyBSDDB جایگزین شده است که رابطی کامل‌تر برای ویژگی‌های تراکنشی کتابخانه BerkeleyDB فراهم می‌کند.

    نسخه‌ی قدیمی ماژول به bsddb185 تغییر نام داده شده و دیگر به‌طور خودکار ساخته نمی‌شود؛ برای فعال‌سازی آن باید Modules/Setup را ویرایش کنید. توجه داشته باشید که بسته‌ی جدید bsddb قرار است با ماژول قدیمی سازگار باشد، بنابراین در صورت یافتن هرگونه ناسازگاری، حتماً باگ گزارش کنید. هنگام ارتقا به Python 2.3، اگر مفسر جدید با نسخه‌ی جدیدی از کتابخانه‌ی زیربنایی BerkeleyDB کامپایل شده باشد، به احتمال بسیار زیاد باید پرونده‌های پایگاه داده‌ی خود را به نسخه‌ی جدید تبدیل کنید. می‌توانید این کار را به‌راحتی با اسکریپت‌های جدید db2pickle.py و pickle2db.py که در پوشه‌ی Tools/scripts توزیع قرار دارند، انجام دهید. اگر تاکنون از بسته‌ی PyBSDDB استفاده کرده‌اید و آن را به‌عنوان bsddb3 ایمپورت کرده‌اید، باید دستورهای import خود را تغییر دهید تا آن را به‌عنوان bsddb ایمپورت کنید.

  • ماژول جدید bz2 رابطی برای کتابخانه‌ی فشرده‌سازی داده bz2 است. داده‌های فشرده‌شده با bz2 معمولاً کوچک‌تر از داده‌های فشرده‌شده‌ی متناظر با zlib هستند. (با مشارکت Gustavo Niemeyer.)

  • مجموعه‌ای از نوع‌های استاندارد تاریخ/زمان در ماژول جدید datetime افزوده شده است. برای جزئیات بیشتر به بخش بعدی مراجعه کنید.

  • کلاس Extension در Distutils اکنون از یک آرگومان سازنده اضافی با نام depends پشتیبانی می‌کند که برای فهرست‌کردن پرونده‌های منبع اضافی‌ای به کار می‌رود که یک ماژول توسعه‌ای به آن‌ها وابسته است. این امر به Distutils امکان می‌دهد در صورت تغییر هر یک از پرونده‌های وابستگی، ماژول را دوباره کامپایل کند. برای مثال، اگر sampmodule.c شامل پرونده‌ی سرآیند sample.h باشد، شیء Extension را به این شکل ایجاد می‌کنید:

    ext = Extension("samp",
                    sources=["sampmodule.c"],
                    depends=["sample.h"])
    

    در این صورت، تغییر دادن sample.h باعث می‌شد ماژول دوباره کامپایل شود. (مشارکت‌شده توسط Jeremy Hylton.)

  • سایر تغییرات جزئی Distutils: اکنون متغیرهای محیطی CC، CFLAGS، CPP، LDFLAGS و CPPFLAGS را بررسی می‌کند و از آن‌ها برای بازنویسی تنظیمات موجود در پیکربندی پایتون استفاده می‌کند (با مشارکت رابرت وبر).

  • پیش‌تر ماژول doctest تنها رشته‌های مستند متدها و توابع عمومی را برای موارد آزمون جستجو می‌کرد، اما اکنون متدها و توابع خصوصی را نیز بررسی می‌کند. تابع DocTestSuite() یک شیء unittest.TestSuite از بدنه‌ی‌ای از آزمون‌های doctest می‌سازد.

  • تابع جدید gc.get_referents(object) فهرستی از تمام اشیائی که object به آن‌ها ارجاع دارد را برمی‌گرداند.

  • ماژول getopt تابع جدیدی به نام gnu_getopt() به دست آورد که از همان آرگومان‌های تابع موجود getopt() پشتیبانی می‌کند، اما از حالت پویش به سبک GNU استفاده می‌کند. تابع موجود getopt() به محض برخورد با آرگومان غیرگزینه‌ای، پردازش گزینه‌ها را متوقف می‌کند، اما در حالت به سبک GNU پردازش ادامه می‌یابد، به این معنا که می‌توان گزینه‌ها و آرگومان‌ها را با هم ترکیب کرد. برای مثال:

    >>> getopt.getopt(['-f', 'filename', 'output', '-v'], 'f:v')
    ([('-f', 'filename')], ['output', '-v'])
    >>> getopt.gnu_getopt(['-f', 'filename', 'output', '-v'], 'f:v')
    ([('-f', 'filename'), ('-v', '')], ['output'])
    

    (مشارکت‌شده توسط Peter Åstrand.)

  • ماژول‌های grp، pwd و resource اکنون تاپل‌های بهبودیافته را برمی‌گردانند:

    >>> import grp
    >>> g = grp.getgrnam('amk')
    >>> g.gr_name, g.gr_gid
    ('amk', 500)
    
  • ماژول gzip اکنون می‌تواند پرونده‌های بزرگ‌تر از ۲ گی‌بایت را پردازش کند.

  • ماژول جدید heapq شامل پیاده‌سازی یک الگوریتم صف هیپ است. هیپ یک ساختار داده شبه‌آرایه‌ای است که آیتم‌ها را در ترتیبی نیمه‌مرتب نگه می‌دارد، به‌گونه‌ای که برای هر اندیس k، heap[k] <= heap[2*k+1] و heap[k] <= heap[2*k+2] برقرار باشد. این امر حذف کوچک‌ترین آیتم را سریع می‌سازد و درج آیتم جدید همراه با حفظ خاصیت هیپ از مرتبه O(log n) است. (برای اطلاعات بیشتر درباره ساختار داده صف اولویت، به https://xlinux.nist.gov/dads//HTML/priorityque.html مراجعه کنید.)

    ماژول heapq توابع heappush() و heappop() را برای افزودن و حذف آیتم‌ها، همراه با حفظ خاصیت هیپ بر روی نوع دیگری از دنباله‌های تغییرپذیر پایتون، ارائه می‌دهد. در ادامه مثالی که از یک فهرست پایتون استفاده می‌کند آمده است:

    >>> import heapq
    >>> heap = []
    >>> for item in [3, 7, 5, 11, 1]:
    ...    heapq.heappush(heap, item)
    ...
    >>> heap
    [1, 3, 5, 11, 7]
    >>> heapq.heappop(heap)
    1
    >>> heapq.heappop(heap)
    3
    >>> heap
    [5, 7, 11]
    

    (با مشارکت کوین اوکانر.)

  • محیط توسعه یکپارچه‌ی IDLE با استفاده از کد پروژه‌ی IDLEfork (https://idlefork.sourceforge.net) به‌روزرسانی شده است. قابل‌توجه‌ترین ویژگی این است که کد در حال توسعه اکنون در یک زیرفرایند اجرا می‌شود، به این معنا که دیگر نیازی به عملیات‌های دستی reload() وجود ندارد. کد هسته‌ی IDLE به‌عنوان بسته‌ی idlelib در کتابخانه استاندارد گنجانده شده است.

  • ماژول imaplib اکنون از IMAP روی SSL پشتیبانی می‌کند. (مشارکت: Piers Lauder و Tino Lange.)

  • ماژول itertools شامل تعدادی تابع مفید برای استفاده با پیمایش‌گرها است که از توابع گوناگون ارائه‌شده توسط زبان‌های ML و Haskell الهام گرفته‌اند. برای مثال، itertools.ifilter(predicate, iterator) تمام عناصری را در پیمایش‌گر برمی‌گرداند که تابع predicate() برای آن‌ها True برمی‌گرداند، و itertools.repeat(obj, N) obj را N بار برمی‌گرداند. تعدادی تابع دیگر در این ماژول وجود دارد؛ برای جزئیات به مستندات مرجع این بسته مراجعه کنید. (با مشارکت Raymond Hettinger.)

  • دو تابع جدید در ماژول math، degrees(rads) و radians(degs)، تبدیل بین رادیان و درجه را انجام می‌دهند. سایر توابع در ماژول math مانند math.sin() و math.cos() همیشه به مقادیر ورودی‌ای نیاز داشته‌اند که بر حسب رادیان اندازه‌گیری شده باشند. همچنین، یک آرگومان اختیاری base به math.log() اضافه شد تا محاسبه لگاریتم‌ها برای مبناهایی غیر از e و 10 آسان‌تر شود. (مشارکت: Raymond Hettinger.)

  • چندین تابع جدید POSIX (getpgid()، killpg()، lchown()، loadavg()، major()، makedev()، minor() و mknod()) به ماژول posix که در زیربنای ماژول os قرار دارد، افزوده شدند. (مشارکت‌شده توسط Gustavo Niemeyer، Geert Jansen و Denis S. Otkidach.)

  • در ماژول os، خانواده‌ی توابع *stat() اکنون می‌تواند کسری از ثانیه را در برچسب زمانی گزارش کند. چنین برچسب‌های زمانی به‌صورت اعداد اعشاری نمایش داده می‌شوند، مشابه مقدار بازگردانده‌شده توسط time.time().

    در طول آزمایش‌ها مشخص شد که اگر مهرهای زمانی اعشاری باشند، برخی از برنامه‌ها خراب می‌شوند. برای سازگاری، هنگام استفاده از رابط تاپلِ stat_result، مهرهای زمانی به‌صورت اعداد صحیح نمایش داده می‌شوند. هنگام استفاده از فیلدهای نام‌دار (قابلیتی که برای نخستین بار در Python 2.2 معرفی شد)، مهرهای زمانی همچنان به‌صورت اعداد صحیح نمایش داده می‌شوند، مگر آنکه os.stat_float_times() برای فعال‌سازی مقادیر بازگشتی اعشاری فراخوانی شود:

    >>> os.stat("/tmp").st_mtime
    1034791200
    >>> os.stat_float_times(True)
    >>> os.stat("/tmp").st_mtime
    1034791200.6335014
    

    در پایتون 2.4، پیش‌فرض به‌گونه‌ای تغییر خواهد کرد که همیشه اعداد اعشاری برگرداند.

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

  • ماژول optparse شامل یک پارسر جدید برای آرگومان‌های خط فرمان است که می‌تواند مقادیر گزینه‌ها را به یک نوع پایتونی خاص تبدیل کند و به‌طور خودکار یک پیام استفاده تولید می‌کند. برای جزئیات بیشتر به بخش بعدی مراجعه کنید.

  • ماژول قدیمی linuxaudiodev که هرگز مستند نشده بود، منسوخ شده است و نسخه‌ی جدیدی با نام ossaudiodev افزوده شده است. نام این ماژول به این دلیل تغییر کرده است که درایورهای صوتی OSS را می‌توان روی پلتفرم‌هایی غیر از لینوکس نیز به کار برد، و رابط آن نیز به روش‌های گوناگون مرتب‌سازی و به‌روزرسانی شده است. (با مشارکت Greg Ward و Nicholas FitzRoy-Dale.)

  • ماژول جدید platform شامل تعدادی تابع است که تلاش می‌کنند ویژگی‌های مختلف پلتفرمی را که شما روی آن اجرا می‌کنید تعیین کنند. توابعی برای به‌دست آوردن معماری، نوع پردازنده، نسخه سیستم‌عامل ویندوز و حتی نسخه توزیع لینوکس وجود دارند. (مشارکت‌شده توسط Marc-André Lemburg.)

  • اشیاء پارسر ارائه‌شده توسط ماژول pyexpat اکنون می‌توانند به‌صورت اختیاری داده‌های نویسه‌ای را بافر کنند، که منجر به فراخوانی‌های کمتر هندلر داده‌های نویسه‌ای شما و در نتیجه کارایی سریع‌تر می‌شود. تنظیم ویژگی buffer_text شیء پارسر روی True بافر کردن را فعال می‌کند.

  • تابع sample(population, k) به ماژول random افزوده شد. population یک دنباله یا شیء xrange است که عناصر یک جامعه را در بر دارد، و sample() بدون جایگزین کردن عناصر انتخاب‌شده، k عنصر از جامعه انتخاب می‌کند. k می‌تواند هر مقداری تا len(population) باشد. برای مثال:

    >>> days = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'St', 'Sn']
    >>> random.sample(days, 3)      # Choose 3 elements
    ['St', 'Sn', 'Th']
    >>> random.sample(days, 7)      # Choose 7 elements
    ['Tu', 'Th', 'Mo', 'We', 'St', 'Fr', 'Sn']
    >>> random.sample(days, 7)      # Choose 7 again
    ['We', 'Mo', 'Sn', 'Fr', 'Tu', 'St', 'Th']
    >>> random.sample(days, 8)      # Can't choose eight
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "random.py", line 414, in sample
          raise ValueError, "sample larger than population"
    ValueError: sample larger than population
    >>> random.sample(xrange(1,10000,2), 10)   # Choose ten odd nos. under 10000
    [3407, 3805, 1505, 7023, 2401, 2267, 9733, 3151, 8083, 9195]
    

    ماژول random اکنون از الگوریتم جدیدی به نام مرسن توئیستر (Mersenne Twister) که در C پیاده‌سازی شده است، استفاده می‌کند. این الگوریتم نسبت به الگوریتم قبلی سریع‌تر است و به‌طور گسترده‌تری مورد مطالعه قرار گرفته است.

    (همه‌ی تغییرات توسط Raymond Hettinger انجام شده‌اند.)

  • ماژول readline نیز تعدادی تابع جدید به دست آورد: get_history_item()، get_current_history_length() و redisplay().

  • ماژول‌های rexec و Bastion مرده اعلام شده‌اند و تلاش برای ایمپورت آن‌ها با RuntimeError شکست می‌خورد. کلاس‌های سبک جدید راه‌های جدیدی برای گریز از محیط اجرای محدودِ فراهم‌شده توسط rexec ارائه می‌دهند و هیچ‌کس علاقه‌ای به اصلاح آن‌ها یا زمانی برای انجام این کار ندارد. اگر برنامه‌هایی دارید که از rexec استفاده می‌کنند، آن‌ها را بازنویسی کنید تا از چیز دیگری استفاده کنند.

    (ادامه دادن به استفاده از پایتون 2.2 یا 2.1 برنامه‌های شما را هیچ امن‌تر نمی‌کند، زیرا باگ‌های شناخته‌شده‌ای در ماژول rexec در آن نسخه‌ها وجود دارد. تکرار می‌کنیم: اگر از rexec استفاده می‌کنید، بلافاصله استفاده از آن را متوقف کنید.)

  • ماژول rotor منسوخ شده است، زیرا الگوریتمی که برای رمزگذاری استفاده می‌کند، امن تلقی نمی‌شود. اگر به رمزگذاری نیاز دارید، از یکی از چندین ماژول AES پایتون که به‌صورت جداگانه در دسترس هستند استفاده کنید.

  • به ماژول shutil تابع move(src, dest) اضافه شد که یک پرونده یا پوشه را به‌صورت بازگشتی به مکانی جدید جابه‌جا می‌کند.

  • پشتیبانی از مدیریت پیشرفته‌تر سیگنال‌های POSIX به signal اضافه شد، اما سپس دوباره حذف شد، زیرا ثابت شد که نمی‌توان آن را به‌طور قابل اعتمادی در پلتفرم‌های مختلف به کار انداخت.

  • ماژول socket اکنون از مهلت‌های زمانی پشتیبانی می‌کند. می‌توانید متد settimeout(t) را روی یک شیء سوکت فراخوانی کنید تا مهلت زمانی t ثانیه‌ای تنظیم شود. عملیات‌های بعدی سوکت که بیش از t ثانیه طول بکشند تا کامل شوند، لغو می‌شوند و استثنای socket.timeout ایجاد می‌کنند.

    پیاده‌سازی اصلی مهلت زمانی کار Tim O'Malley بود. Michael Gilfix آن را در ماژول socket پایتون ادغام کرد و آن را از یک بازبینی طولانی عبور داد. پس از ثبت کد در مخزن، Guido van Rossum بخش‌هایی از آن را بازنویسی کرد. (این نمونه‌ی خوبی از یک فرایند توسعه‌ی مشارکتی در عمل است.)

  • در ویندوز، ماژول socket اکنون به همراه پشتیبانی از لایه سوکت‌های امن (SSL) عرضه می‌شود.

  • مقدار ماکروی C PYTHON_API_VERSION اکنون در سطح پایتون به‌صورت sys.api_version در دسترس قرار گرفته است. استثنای جاری را می‌توان با فراخوانی تابع جدید sys.exc_clear() پاک کرد.

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

  • ماژول جدید textwrap شامل توابعی برای سطربندی رشته‌هایی است که حاوی پاراگراف‌هایی از متن هستند. تابع wrap(text, width) یک رشته می‌گیرد و فهرستی حاوی متن تقسیم‌شده به سطرهایی که طولشان از عرض انتخاب‌شده بیشتر نیست، برمی‌گرداند. تابع fill(text, width) یک رشته‌ی واحد برمی‌گرداند که مجدداً قالب‌بندی شده است تا در سطرهایی که طولشان از عرض انتخاب‌شده بیشتر نیست جای گیرد. (همان‌طور که می‌توانید حدس بزنید، fill() بر پایه‌ی wrap() ساخته شده است. برای مثال:

    >>> import textwrap
    >>> paragraph = "Not a whit, we defy augury: ... more text ..."
    >>> textwrap.wrap(paragraph, 60)
    ["Not a whit, we defy augury: there's a special providence in",
     "the fall of a sparrow. If it be now, 'tis not to come; if it",
     ...]
    >>> print textwrap.fill(paragraph, 35)
    Not a whit, we defy augury: there's
    a special providence in the fall of
    a sparrow. If it be now, 'tis not
    to come; if it be not to come, it
    will be now; if it be not now, yet
    it will come: the readiness is all.
    >>>
    

    این ماژول همچنین شامل کلاس TextWrapper است که در واقع راهبرد شکستن سطرهای متن را پیاده‌سازی می‌کند. هم کلاس TextWrapper و هم توابع wrap() و fill() از تعدادی آرگومان کلیدواژه‌ای اضافی برای تنظیم دقیق قالب‌بندی پشتیبانی می‌کنند؛ برای جزئیات به مستندات ماژول مراجعه کنید. (با مشارکت گرگ وارد.)

  • ماژول‌های thread و threading اکنون ماژول‌های همراهی دارند، dummy_thread و dummy_threading، که برای پلتفرم‌هایی که از نخ‌ها پشتیبانی نمی‌کنند، پیاده‌سازی بی‌اثری از رابط ماژول thread ارائه می‌دهند. هدف این است که ماژول‌های آگاه از نخ (ماژول‌هایی که برای اجرا بر نخ‌ها تکیه نمی‌کنند) با قرار دادن کد زیر در ابتدای آن‌ها ساده‌سازی شوند:

    try:
        import threading as _threading
    except ImportError:
        import dummy_threading as _threading
    

    در این مثال، _threading به‌عنوان نام ماژول استفاده می‌شود تا روشن باشد که ماژول مورد استفاده، لزوماً ماژول واقعی threading نیست. کد می‌تواند صرف‌نظر از اینکه نخ‌ها پشتیبانی می‌شوند یا نه، توابع را فراخوانی کند و از کلاس‌های _threading استفاده کند؛ با این کار از یک دستور if اجتناب می‌شود و کد کمی واضح‌تر می‌شود. این ماژول به‌طور جادویی باعث نمی‌شود که کد چندنخی بدون نخ اجرا شود؛ کدی که منتظر است تا نخ دیگری بازگردد یا کاری انجام دهد، صرفاً برای همیشه معلق می‌ماند.

  • تابع strptime() ماژول time مدت‌هاست که مایه‌ی آزار بوده است، زیرا از پیاده‌سازی strptime() در کتابخانه C پلتفرم استفاده می‌کند و پلتفرم‌های مختلف گاهی باگ‌های عجیبی دارند. Brett Cannon یک پیاده‌سازی قابل حمل ارائه کرده است که به پایتون خالص نوشته‌شده و باید در همه پلتفرم‌ها رفتاری یکسان داشته باشد.

  • ماژول جدید timeit به اندازه‌گیری مدت زمان اجرای قطعه‌کدهای پایتون کمک می‌کند. پرونده‌ی timeit.py را می‌توان مستقیماً از خط فرمان اجرا کرد، یا کلاس Timer ماژول را می‌توان ایمپورت کرد و مستقیماً از آن استفاده کرد. در اینجا مثال کوتاهی آمده است که مشخص می‌کند آیا تبدیل یک رشته‌ی ۸-بیتی به یونیکد با الحاق یک رشته‌ی یونیکد خالی به آن سریع‌تر است، یا با استفاده از تابع unicode():

    import timeit
    
    timer1 = timeit.Timer('unicode("abc")')
    timer2 = timeit.Timer('"abc" + u""')
    
    # Run three trials
    print timer1.repeat(repeat=3, number=100000)
    print timer2.repeat(repeat=3, number=100000)
    
    # On my laptop this outputs:
    # [0.36831796169281006, 0.37441694736480713, 0.35304892063140869]
    # [0.17574405670166016, 0.18193507194519043, 0.17565798759460449]
    
  • ماژول Tix برای نسخه‌ی فعلی بسته‌ی Tix، رفع اشکال‌ها و به‌روزرسانی‌های گوناگونی دریافت کرده است.

  • ماژول Tkinter اکنون با نسخه‌ای از Tcl که نخ‌بندی در آن فعال است کار می‌کند. مدل نخ‌بندی Tcl ایجاب می‌کند که به ابزارک‌ها فقط از نخی که در آن ایجاد شده‌اند دسترسی پیدا شود؛ دسترسی از نخی دیگر می‌تواند باعث پنیک (panic) شدن Tcl شود. برای برخی از رابط‌های Tcl، Tkinter اکنون هنگامی که از نخی دیگر به ابزارکی دسترسی پیدا می‌شود، به‌طور خودکار با مارشال‌کردن یک فرمان، ارسال آن به نخ صحیح و انتظار برای نتایج، از این وضعیت اجتناب می‌کند. رابط‌های دیگر را نمی‌توان به‌طور خودکار مدیریت کرد، اما Tkinter اکنون در چنین دسترسی‌ای یک استثنا ایجاد می‌کند تا حداقل بتوانید از وجود مشکل مطلع شوید. برای توضیح دقیق‌تر این تغییر، به https://mail.python.org/pipermail/python-dev/2002-December/031107.html مراجعه کنید. (پیاده‌سازی‌شده توسط Martin von Löwis.)

  • فراخوانی متدهای Tcl از طریق _tkinter دیگر فقط رشته برنمی‌گرداند. در عوض، اگر Tcl اشیاء دیگری برگرداند، این اشیاء در صورت وجود به معادل پایتونی خود تبدیل می‌شوند و در صورت نبود معادل پایتونی، با شیء _tkinter.Tcl_Obj پوشش داده می‌شوند. این رفتار را می‌توان از طریق متد wantobjects() اشیاء tkapp کنترل کرد.

    هنگام استفاده از _tkinter از طریق ماژول Tkinter (همان‌طور که بیشتر برنامه‌های Tkinter انجام می‌دهند)، این ویژگی همیشه فعال است. این موضوع نباید مشکلات سازگاری ایجاد کند، زیرا Tkinter در صورت امکان، همیشه نتایج رشته را به نوع‌های پایتون تبدیل می‌کند.

    اگر ناسازگاری‌ای یافت شود، می‌توان با تنظیم متغیر wantobjects در ماژول Tkinter روی false پیش از ایجاد نخستین شیء tkapp، رفتار قدیمی را بازگردانی کرد.

    import Tkinter
    Tkinter.wantobjects = 0
    

    هرگونه خرابی ناشی از این تغییر باید به‌عنوان یک باگ گزارش شود.

  • ماژول UserDict یک کلاس جدید به نام DictMixin دارد که تمام متدهای دیکشنری را برای کلاس‌هایی که از قبل دارای رابط نگاشت حداقلی هستند، تعریف می‌کند. این امر نوشتن کلاس‌هایی که باید بتوان آن‌ها را به‌جای دیکشنری‌ها به کار برد، مانند کلاس‌های موجود در ماژول shelve، را به‌طور چشمگیری ساده‌تر می‌کند.

    افزودن میکس‌این به‌عنوان ابرقلاس، هرگاه کلاس __getitem__()، __setitem__()، __delitem__() و keys() را تعریف کند، رابط کامل دیکشنری را فراهم می‌کند. برای مثال:

    >>> import UserDict
    >>> class SeqDict(UserDict.DictMixin):
    ...     """Dictionary lookalike implemented with lists."""
    ...     def __init__(self):
    ...         self.keylist = []
    ...         self.valuelist = []
    ...     def __getitem__(self, key):
    ...         try:
    ...             i = self.keylist.index(key)
    ...         except ValueError:
    ...             raise KeyError
    ...         return self.valuelist[i]
    ...     def __setitem__(self, key, value):
    ...         try:
    ...             i = self.keylist.index(key)
    ...             self.valuelist[i] = value
    ...         except ValueError:
    ...             self.keylist.append(key)
    ...             self.valuelist.append(value)
    ...     def __delitem__(self, key):
    ...         try:
    ...             i = self.keylist.index(key)
    ...         except ValueError:
    ...             raise KeyError
    ...         self.keylist.pop(i)
    ...         self.valuelist.pop(i)
    ...     def keys(self):
    ...         return list(self.keylist)
    ...
    >>> s = SeqDict()
    >>> dir(s)      # See that other dictionary methods are implemented
    ['__cmp__', '__contains__', '__delitem__', '__doc__', '__getitem__',
     '__init__', '__iter__', '__len__', '__module__', '__repr__',
     '__setitem__', 'clear', 'get', 'has_key', 'items', 'iteritems',
     'iterkeys', 'itervalues', 'keylist', 'keys', 'pop', 'popitem',
     'setdefault', 'update', 'valuelist', 'values']
    

    (با مشارکت Raymond Hettinger.)

  • پیاده‌سازی DOM در xml.dom.minidom اکنون می‌تواند با ارائه‌ی یک آرگومان اختیاری کدگذاری به متدهای toxml() و toprettyxml() گره‌های DOM، خروجی XML را با کدگذاری مشخصی تولید کند.

  • ماژول xmlrpclib اکنون از یک افزونه‌ی XML-RPC برای مدیریت مقدارهای داده‌ای تهی (nil) مانند None پایتون پشتیبانی می‌کند. مقدارهای تهی همیشه هنگام مارشال‌گشایی یک پاسخ XML-RPC پشتیبانی می‌شوند. برای تولید درخواست‌های حاوی None، باید هنگام ایجاد یک نمونه‌ی Marshaller مقدار درستی برای پارامتر allow_none ارائه کنید.

  • ماژول جدید DocXMLRPCServer امکان نوشتن سرورهای XML-RPC خودمستندساز را فراهم می‌کند. برای دیدن آن در عمل، آن را در حالت نمایشی (به‌عنوان یک برنامه) اجرا کنید. هدایت مرورگر وب به سرور RPC، مستنداتی به سبک pydoc تولید می‌کند؛ و هدایت xmlrpclib به سرور، امکان فراخوانی متدهای واقعی را فراهم می‌کند. (مشارکت‌شده توسط برایان کوینلان.)

  • پشتیبانی از دامنه‌های اینترنتی بین‌المللی (RFCهای 3454، 3490، 3491 و 3492) اضافه شده است. از کدگذاری "idna" می‌توان برای تبدیل بین نام دامنه‌ی یونیکدی و کدگذاری سازگار با اسکی (ACE) همان نام استفاده کرد.

    >{}>{}> u"www.Alliancefrançaise.nu".encode("idna")
    'www.xn--alliancefranaise-npb.nu'
    

    ماژول socket نیز توسعه یافته است تا نام‌های میزبان یونیکد را پیش از پاس دادن آن‌ها به کتابخانه‌ی C، به‌طور شفاف به نسخه‌ی ACE تبدیل کند. ماژول‌هایی مانند httplib و ftplib) که با نام‌های میزبان سروکار دارند، نیز از نام‌های میزبان یونیکد پشتیبانی می‌کنند؛ httplib همچنین سرآیندهای HTTP Host را با استفاده از نسخه‌ی ACE نام دامنه ارسال می‌کند. urllib از URL‌های یونیکد با نام‌های میزبان غیر اسکی پشتیبانی می‌کند، به شرطی که بخش path از URL فقط اسکی باشد.

    برای پیاده‌سازی این تغییر، ماژول stringprep، ابزار mkstringprep و کدگذاری punycode افزوده شده‌اند.

نوع تاریخ/زمان

انواع تاریخ و زمان مناسب برای بیان مهر‌های زمانی به‌عنوان ماژول datetime افزوده شدند. این نوع‌ها از گاه‌شماری‌های مختلف یا بسیاری از قابلیت‌های پیشرفته پشتیبانی نمی‌کنند و صرفاً به مبانی نمایش زمان پایبند هستند.

سه نوع اصلی عبارت‌اند از: date که روز، ماه و سال را نشان می‌دهد؛ time که از ساعت، دقیقه و ثانیه تشکیل شده است؛ و datetime که تمام ویژگی‌های هر دو date و time را در بر می‌گیرد. همچنین کلاس timedelta وجود دارد که تفاوت میان دو نقطه از زمان را نشان می‌دهد، و منطق منطقه زمانی توسط کلاس‌هایی که از کلاس انتزاعی tzinfo ارث‌بری می‌کنند، پیاده‌سازی شده است.

می‌توانید نمونه‌هایی از date و time را یا با دادن آرگومان‌های کلیدواژه‌ای به سازنده‌ی مناسب، مثلاً datetime.date(year=1972, month=10, day=15)، یا با استفاده از یکی از چندین متد کلاس ایجاد کنید. برای مثال، متد کلاس today() تاریخ محلی جاری را برمی‌گرداند.

پس از ایجاد شدن، نمونه‌های کلاس‌های تاریخ/زمان همگی تغییرناپذیر هستند. تعدادی متد برای تولید رشته‌های قالب‌بندی‌شده از اشیاء وجود دارد:

>>> import datetime as dt
>>> now = dt.datetime.now()
>>> now.isoformat()
'2002-12-30T21:27:03.994956'
>>> now.ctime()  # Only available on date, datetime
'Mon Dec 30 21:27:03 2002'
>>> now.strftime('%Y %d %b')
'2002 30 Dec'

متد replace() به شما اجازه می‌دهد یک یا چند فیلد از یک نمونه‌ی date یا datetime را تغییر دهید و نمونه‌ی جدیدی برمی‌گرداند:

>>> d = dt.datetime.now()
>>> d
datetime.datetime(2002, 12, 30, 22, 15, 38, 827738)
>>> d.replace(year=2001, hour=12)
datetime.datetime(2001, 12, 30, 12, 15, 38, 827738)
>>>

می‌توان نمونه‌ها را مقایسه کرد، هش کرد و به رشته تبدیل کرد (نتیجه همانند نتیجه‌ی isoformat() است). نمونه‌های date و datetime را می‌توان از یکدیگر کم کرد و به نمونه‌های timedelta افزود. بزرگ‌ترین قابلیت غایب این است که کتابخانه استاندارد از پارس کردن رشته‌ها و بازگرداندن یک date یا datetime پشتیبانی نمی‌کند.

برای اطلاعات بیشتر، به مستندات مرجع ماژول مراجعه کنید. (ارائه‌شده توسط تیم پیترز.)

ماژول optparse

ماژول getopt تجزیه‌ی ساده‌ی آرگومان‌های خط فرمان را فراهم می‌کند. ماژول جدید optparse (که در اصل Optik نام داشت) تجزیه‌ی پیشرفته‌تر خط فرمان را ارائه می‌کند که از قراردادهای یونیکس پیروی می‌کند، خروجی --help را به‌طور خودکار ایجاد می‌کند و می‌تواند برای گزینه‌های مختلف، اکشن‌های متفاوتی انجام دهد.

شما با ایجاد یک نمونه از OptionParser شروع می‌کنید و به آن می‌گویید که گزینه‌های برنامه‌تان چه هستند.

import sys
from optparse import OptionParser

op = OptionParser()
op.add_option('-i', '--input',
              action='store', type='string', dest='input',
              help='set input filename')
op.add_option('-l', '--length',
              action='store', type='int', dest='length',
              help='set maximum length of output')

سپس تجزیه خط فرمان با فراخوانی متد parse_args() انجام می‌شود.

options, args = op.parse_args(sys.argv[1:])
print options
print args

این یک شیء حاوی تمام مقادیر گزینه‌ها و یک فهرست از رشته‌ها شامل آرگومان‌های باقی‌مانده را برمی‌گرداند.

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

$ ./python opt.py -i data arg1
<Values at 0x400cad4c: {'input': 'data', 'length': None}>
['arg1']
$ ./python opt.py --input=data --length=4
<Values at 0x400cad2c: {'input': 'data', 'length': 4}>
[]
$

پیام راهنما به‌صورت خودکار برای شما تولید می‌شود:

$ ./python opt.py --help
usage: opt.py [options]

options:
  -h, --help            show this help message and exit
  -iINPUT, --input=INPUT
                        set input filename
  -lLENGTH, --length=LENGTH
                        set maximum length of output
$

برای جزئیات بیشتر به مستندات ماژول مراجعه کنید.

Optik توسط گرگ وارد، همراه با پیشنهادهایی از خوانندگان Getopt SIG نوشته شده است.

Pymalloc: تخصیص‌دهنده‌ی تخصصی اشیاء

Pymalloc، یک تخصیص‌دهنده‌ی تخصصی برای اشیاء که توسط Vladimir Marangozov نوشته‌شده بود، قابلیتی بود که به Python 2.1 اضافه شد. Pymalloc به‌گونه‌ای طراحی‌شده که سریع‌تر از malloc() سیستم باشد و برای الگوهای تخصیص رایج در برنامه‌های پایتون، سربار حافظه‌ی کمتری داشته باشد. این تخصیص‌دهنده از تابع malloc() زبان C برای به‌دست‌آوردن استخرهای بزرگ حافظه استفاده می‌کند و سپس درخواست‌های حافظه‌ی کوچک‌تر را از این استخرها برآورده می‌کند.

در نسخه‌های 2.1 و 2.2، pymalloc یک قابلیت آزمایشی بود و به‌صورت پیش‌فرض فعال نبود؛ هنگام کامپایل پایتون باید با ارائه‌ی گزینه‌ی --with-pymalloc به اسکریپت configure آن را به‌طور صریح فعال می‌کردید. در نسخه‌ی 2.3، pymalloc بهبودهای بیشتری یافته است و اکنون به‌صورت پیش‌فرض فعال است؛ برای غیرفعال کردن آن باید گزینه‌ی --without-pymalloc را ارائه کنید.

این تغییر برای کد نوشته‌شده در پایتون شفاف است؛ با این حال، pymalloc ممکن است باگ‌هایی را در توسعه‌های C آشکار کند. نویسندگان ماژول‌های توسعه‌ای C باید کد خود را با pymalloc فعال آزمایش کنند، زیرا برخی کدهای نادرست ممکن است در زمان اجرا باعث برون‌ریزی هسته شوند.

یک خطای به‌ویژه رایج وجود دارد که باعث بروز مشکلات می‌شود. تعدادی از توابع تخصیص حافظه در API زبان C پایتون، پیش‌تر صرفاً نام‌های مستعاری برای malloc() و free() کتابخانه‌ی C بودند؛ به این معنا که اگر ناخواسته توابع ناسازگاری را فراخوانی می‌کردید، خطا آشکار نمی‌شد. وقتی تخصیص‌دهنده اشیاء فعال باشد، این توابع دیگر نام مستعاری برای malloc() و free() نیستند و فراخوانی تابع اشتباه برای آزاد کردن حافظه ممکن است به برون‌ریزی هسته منجر شود. برای مثال، اگر حافظه با استفاده از PyObject_Malloc() تخصیص داده شده باشد، باید با استفاده از PyObject_Free() آزاد شود، نه با free(). چند ماژول از ماژول‌های همراه پایتون گرفتار این مشکل شدند و باید اصلاح می‌شدند؛ بی‌تردید ماژول‌های شخص ثالث بیشتری نیز هستند که همین مشکل را خواهند داشت.

به عنوان بخشی از این تغییر، رابط‌های متعدد و گیج‌کننده برای تخصیص حافظه در دو خانواده‌ی API ادغام شدند. حافظه‌ای که با یکی از خانواده‌ها تخصیص یافته است، نباید با توابع خانواده‌ی دیگر دستکاری شود. یک خانواده برای تخصیص بخش‌هایی از حافظه و خانواده‌ی دیگری از توابع به‌طور خاص برای تخصیص شیءهای پایتون وجود دارد.

  • برای تخصیص دادن و آزاد کردن تکه‌ای نامتمایز از حافظه، از خانواده «حافظه خام» استفاده کنید: PyMem_Malloc()، PyMem_Realloc() و PyMem_Free().

  • خانواده‌ی «حافظه‌ی شیء» رابط امکان pymalloc است که در بالا توضیح داده شد و به سمت تعداد زیادی تخصیص «کوچک» گرایش دارد: PyObject_Malloc()، PyObject_Realloc() و PyObject_Free().

  • برای تخصیص دادن و آزاد کردن اشیاء پایتون، از خانواده‌ی «object» شامل PyObject_New، PyObject_NewVar و PyObject_Del() استفاده کنید.

به لطف تلاش‌های فراوان تیم پیترز، pymalloc در نسخه‌ی 2.3 نیز قابلیت‌هایی برای اشکال‌زدایی فراهم می‌کند که بازنویسی حافظه (memory overwrite) و آزادسازی دوباره (double free) را هم در ماژول‌های توسعه‌ای و هم در خود مفسر شناسایی می‌کنند. برای فعال کردن این پشتیبانی، یک نسخه‌ی اشکال‌زدایی از مفسر پایتون را با اجرای configure به همراه --with-pydebug کامپایل کنید.

برای کمک به نویسندگان توسعه‌ها، پرونده‌ی سرآیند Misc/pymemcompat.h که همراه با کد منبع پایتون 2.3 توزیع می‌شود، به توسعه‌های پایتون اجازه می‌دهد هنگام کامپایل در برابر هر نسخه از پایتون از 1.5.2 به بعد، از رابط‌های 2.3 برای تخصیص حافظه استفاده کنند. شما این پرونده را از توزیع کد منبع پایتون کپی کرده و آن را همراه کد منبع توسعه‌ی خود قرار می‌دهید.

همچنین ملاحظه نمائید

https://hg.python.org/cpython/file/default/Objects/obmalloc.c

برای جزئیات کامل پیاده‌سازی pymalloc، به کامنت‌های ابتدای پرونده‌ی Objects/obmalloc.c در کد منبع پایتون مراجعه کنید. پیوند بالا به این پرونده در مرورگر SVN وب‌سایت python.org اشاره می‌کند.

تغییرات ساخت و API زبان C

تغییرات در فرایند ساخت پایتون و در C API شامل موارد زیر است:

  • پیاده‌سازی تشخیص چرخه که در زباله‌روبی استفاده می‌شود، پایداری خود را ثابت کرده است، بنابراین اکنون الزامی شده است. دیگر نمی‌توانید پایتون را بدون آن کامپایل کنید و سوییچ --with-cycle-gc از configure حذف شده است.

  • پایتون اکنون می‌تواند به‌صورت اختیاری به‌عنوان یک کتابخانه اشتراکی (libpython2.3.so) ساخته شود؛ این کار با ارائه‌ی گزینه‌ی --enable-shared هنگام اجرای اسکریپت configure پایتون انجام می‌شود. (مشارکت‌شده توسط اوندری پالکوفسکی.)

  • ماکروهای DL_EXPORT و DL_IMPORT اکنون منسوخ شده‌اند. توابع مقداردهی اولیه برای ماژول‌های توسعه‌ای پایتون باید اکنون با استفاده از ماکروی جدید PyMODINIT_FUNC اعلام شوند، در حالی که هسته پایتون به‌طور کلی از ماکروهای PyAPI_FUNC و PyAPI_DATA استفاده خواهد کرد.

  • مفسر را می‌توان با ارائه‌ی --without-doc-strings به اسکریپت configure، بدون هیچ رشته مستندی برای توابع و ماژول‌های توکار کامپایل کرد. این کار پرونده اجرایی پایتون را حدود ۱۰٪ کوچک‌تر می‌کند، اما به این معنا نیز خواهد بود که نمی‌توانید برای توکارهای پایتون کمک بگیرید. (مشارکت توسط گوستاوو نیمایر.)

  • ماکروی PyArg_NoArgs() اکنون منسوخ شده است و کدی که از آن استفاده می‌کند باید تغییر کند. برای پایتون 2.2 و نسخه‌های بعدی، جدول تعریف متد می‌تواند پرچم METH_NOARGS را مشخص کند که نشان می‌دهد هیچ آرگومانی وجود ندارد، و سپس می‌توان بررسی آرگومان را حذف کرد. اگر سازگاری با نسخه‌های پایتون پیش از 2.2 اهمیت دارد، کد می‌تواند به‌جای آن از PyArg_ParseTuple(args, "") استفاده کند، اما این کار کندتر از استفاده از METH_NOARGS خواهد بود.

  • PyArg_ParseTuple() نویسه‌های قالب جدیدی را برای اندازه‌های گوناگون اعداد صحیح بدون علامت می‌پذیرد: B برای unsigned char، H برای unsigned short int، I برای unsigned int و K برای unsigned long long.

  • تابع جدیدی با نام PyObject_DelItemString(mapping, char *key) به‌عنوان شکل مختصری برای PyObject_DelItem(mapping, PyString_New(key)) اضافه شد.

  • اشیاء پرونده اکنون بافر رشته‌ای داخلی خود را به شکل متفاوتی مدیریت می‌کنند و در صورت نیاز آن را به‌صورت نمایی افزایش می‌دهند. این امر باعث می‌شود آزمون‌های بنچمارک موجود در Lib/test/test_bufio.py به‌طور قابل‌توجهی سریع‌تر شوند (بر اساس یک اندازه‌گیری، از ۵۷ ثانیه به ۱٫۷ ثانیه).

  • اکنون می‌توان با تنظیم یکی از پرچم‌های METH_CLASS یا METH_STATIC در ساختار PyMethodDef یک متد، متدهای کلاس و ایستا را برای یک نوع توسعه‌ای C تعریف کرد.

  • پایتون اکنون شامل رونوشتی از کد منبع پارسر XML اکسپت (Expat) است که هرگونه وابستگی به نسخه‌ی سیستمی یا نصب محلی Expat را از بین می‌برد.

  • اگر اشیاء نوع را به‌صورت پویا در ماژول توسعه‌ای خود تخصیص می‌دهید، باید از تغییری در قواعد مربوط به ویژگی‌های __module__ و __name__ آگاه باشید. به‌طور خلاصه، باید مطمئن شوید که دیکشنری نوع شامل کلید '__module__' است؛ قرار دادن نام ماژول به‌عنوان بخشی از نام نوع که پیش از آخرین نقطه قرار دارد، دیگر اثر مطلوب را نخواهد داشت. برای جزئیات بیشتر، مستندات مرجع API یا کد منبع را بخوانید.

تغییرات خاص پورت

پشتیبانی از پورت برای OS/2 شرکت IBM که از محیط ران‌تایم EMX استفاده می‌کند، در درخت منبع اصلی پایتون ادغام شد. EMX یک لایه شبیه‌سازی POSIX روی APIهای سیستمی OS/2 است. پورت پایتون برای EMX تلاش می‌کند تمام قابلیت‌های شبه‌POSIX ارائه‌شده از سوی ران‌تایم EMX را پشتیبانی کند و عمدتاً موفق است؛ fork() و fcntl() به‌واسطه محدودیت‌های لایه شبیه‌سازی زیرین محدود شده‌اند. پورت استاندارد OS/2، که از کامپایلر Visual Age شرکت IBM استفاده می‌کند، نیز به عنوان بخشی از ادغام پورت EMX در CVS، پشتیبانی از معناشناسی ایمپورت حساس به بزرگی و کوچکی حروف را به دست آورد. (با مشارکت Andrew MacIntyre.)

در MacOS، اکثر ماژول‌های جعبه‌ابزار (toolbox) برای بهبود سازگاری با نسخه‌های پیشین، با پیوند ضعیف (weak linking) ساخته شده‌اند. این بدان معناست که اگر حتی یک روتین (routine) هم در نسخه‌ی فعلی سیستم‌عامل وجود نداشته باشد، ماژول‌ها دیگر هنگام بارگذاری شکست نمی‌خورند. در عوض، فراخوانی روتین مفقود یک استثنا مطرح می‌کند. (مشارکت‌کننده: Jack Jansen.)

پرونده‌های مشخصات RPM، که در پوشه‌ی Misc/RPM/ در توزیع کد منبع پایتون قرار دارند، برای نسخه‌ی 2.3 به‌روزرسانی شدند. (مشارکت از سوی Sean Reifschneider.)

از دیگر پلتفرم‌های جدیدی که اکنون پایتون از آن‌ها پشتیبانی می‌کند، می‌توان به AtheOS (http://www.atheos.cx/)، GNU/Hurd و OpenVMS اشاره کرد.

سایر تغییرات و رفع اشکالات

طبق معمول، تعداد زیادی بهبود و رفع اشکال دیگر در سراسر درخت سورس پراکنده بودند. جست‌وجو در گزارش‌های تغییرات CVS نشان می‌دهد که بین پایتون 2.2 و 2.3، ۵۲۳ وصل اعمال شده و ۵۱۴ اشکال برطرف شده است. هر دو رقم احتمالاً کم‌برآورد هستند.

برخی از مهم‌ترین تغییرات عبارت‌اند از:

  • اگر متغیر محیطی PYTHONINSPECT تنظیم شده باشد، مفسر پایتون پس از اجرای یک برنامه پایتون وارد اعلان تعاملی می‌شود، گویی که پایتون با گزینه‌ی -i فراخوانی شده است. این متغیر محیطی را می‌توان پیش از اجرای مفسر پایتون تنظیم کرد، یا می‌توان آن را توسط برنامه پایتون به‌عنوان بخشی از اجرای آن تنظیم کرد.

  • اسکریپت regrtest.py اکنون راهی برای اجازه دادن به «همه منابع به‌جز foo» فراهم می‌کند. نام منبعی که به گزینه‌ی -u داده می‌شود، اکنون می‌تواند یک خط تیره ('-') به‌عنوان پیشوند داشته باشد تا به معنای «حذف این منبع» باشد. برای مثال، گزینه‌ی '-uall,-bsddb' را می‌توان برای فعال‌سازی استفاده از همه منابع به‌جز bsddb به کار برد.

  • ابزارهای استفاده‌شده برای ساخت مستندات اکنون علاوه بر Unix، تحت Cygwin نیز کار می‌کنند.

  • آپ‌کد SET_LINENO حذف شده است. در گذشته‌های بسیار دور، این آپ‌کد برای تولید شماره سطرها در ردگیری‌ها و پشتیبانی از توابع ردگیری (مثلاً برای pdb) لازم بود. از Python 1.5 به بعد، شماره سطرها در ردگیری‌ها با استفاده از سازوکار متفاوتی که با "python -O" کار می‌کند، محاسبه شده‌اند. برای Python 2.3، Michael Hudson طرح‌واره‌ای مشابه برای تعیین زمان فراخوانی تابع ردگیری پیاده‌سازی کرد و نیاز به SET_LINENO را به‌طور کامل از بین برد.

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

    توسعه‌های C که به فیلد f_lineno در اشیای فریم دسترسی دارند، باید به‌جای آن PyCode_Addr2Line(f->f_code, f->f_lasti) را فراخوانی کنند. این کار این اثر افزوده را نیز خواهد داشت که کد در نسخه‌های قدیمی‌تر پایتون، تحت «python -O» به‌شکل مطلوب کار کند.

    یک قابلیت جدید و جالب این است که توابع ردگیری اکنون می‌توانند مقداری را به ویژگی f_lineno اشیاء فریم منتسب کنند و سطری که در ادامه اجرا خواهد شد را تغییر دهند. دستور jump با بهره‌گیری از این قابلیت جدید به اشکال‌زدای pdb افزوده شده است. (پیاده‌سازی‌شده توسط Richie Hindle.)

انتقال به پایتون 2.3

این بخش تغییراتی را فهرست می‌کند که پیش‌تر توضیح داده‌شده‌اند و ممکن است نیازمند تغییراتی در کد شما باشند:

  • yield اکنون همیشه یک کلیدواژه است؛ اگر در کد خود از آن به‌عنوان نام متغیر استفاده کرده‌اید، باید نام دیگری را انتخاب کنید.

  • برای رشته‌های X و Y، X in Y اکنون در صورتی کار می‌کند که X بیش از یک نویسه طول داشته باشد.

  • اکنون سازنده‌ی نوع int() زمانی که یک رشته یا عدد ممیز شناور برای جای‌گرفتن در یک عدد صحیح بیش از حد بزرگ باشد، به‌جای ایجاد OverflowError یک عدد صحیح بلند بازمی‌گرداند.

  • اگر رشته‌های یونیکدی دارید که حاوی نویسه‌های ۸-بیتی هستند، باید کدگذاری پرونده (UTF-8، Latin-1 یا هر چیز دیگر) را با افزودن یک کامنت به ابتدای پرونده اعلام کنید. برای اطلاعات بیشتر به بخش PEP 263: کدگذاری‌های کد منبع مراجعه کنید.

  • فراخوانی متدهای Tcl از طریق _tkinter دیگر فقط رشته برنمی‌گرداند. در عوض، اگر Tcl اشیاء دیگری برگرداند، این اشیاء در صورتی که معادل پایتونی داشته باشند به آن تبدیل می‌شوند و در صورت نبود معادل پایتونی، با یک شیء _tkinter.Tcl_Obj پوشش داده می‌شوند.

  • مقادیر لفظی بزرگ مبنای هشت و مبنای شانزده مانند 0xffffffff اکنون هشدار FutureWarning ایجاد می‌کنند. در حال حاضر، این مقادیر به‌صورت اعداد ۳۲ بیتی ذخیره می‌شوند و مقداری منفی به دست می‌دهند، اما در پایتون 2.4 به اعداد صحیح بلند مثبت تبدیل خواهند شد.

    چند راه برای رفع این هشدار وجود دارد. اگر واقعاً به یک عدد مثبت نیاز دارید، کافی است یک L به انتهای مقدار لفظی اضافه کنید. اگر سعی دارید یک عدد صحیح ۳۲ بیتی به دست آورید که بیت‌های پایین آن تنظیم شده‌اند و پیش‌تر از عبارتی مانند ~(1 << 31) استفاده کرده‌اید، احتمالاً روشن‌ترین راه این است که با همه بیت‌های تنظیم‌شده شروع کنید و بیت‌های بالایی مورد نظر را صفر کنید. برای مثال، برای صفر کردن فقط بیت بالایی (بیت ۳۱)، می‌توانید 0xffffffffL &~(1L<<31) بنویسید.

  • دیگر نمی‌توانید ادعاها را با انتساب به __debug__ غیرفعال کنید.

  • تابع setup() در Distutils آرگومان‌های کلیدواژه‌ای جدید گوناگونی مانند depends به دست آورده است. نسخه‌های قدیمی Distutils در صورت دریافت کلیدواژه‌های ناشناخته خاتمه می‌یابند. یک راه‌حل این است که وجود تابع جدید get_distutil_options() را در setup.py خود بررسی کنید و کلیدواژه‌های جدید را تنها با نسخه‌ای از Distutils که از آن‌ها پشتیبانی می‌کند استفاده کنید:

    from distutils import core
    
    kw = {'sources': 'foo.c', ...}
    if hasattr(core, 'get_distutil_options'):
        kw['depends'] = ['foo.h']
    ext = Extension(**kw)
    
  • استفاده از None به‌عنوان نام متغیر اکنون منجر به هشدار SyntaxWarning خواهد شد.

  • نام نوع‌های توسعه‌ای تعریف‌شده توسط ماژول‌های همراه پایتون، اکنون شامل ماژول و یک '.' پیش از نام نوع هستند.

قدردانی‌ها

نویسنده می‌خواهد از افراد زیر برای ارائه پیشنهادها، اصلاحات و کمک در پیش‌نویس‌های مختلف این مقاله تشکر کند: Jeff Bauer, Simon Brunning, Brett Cannon, Michael Chermside, Andrew Dalke, Scott David Daniels, Fred L. Drake, Jr., David Fraser, Kelly Gerber, Raymond Hettinger, Michael Hudson, Chris Lambert, Detlef Lannert, Martin von Löwis, Andrew MacIntyre, Lalo Martins, Chad Netzer, Gustavo Niemeyer, Neal Norwitz, Hans Nowak, Chris Reedy, Francesco Ricciardi, Vinay Sajip, Neil Schemenauer, Roman Suzi, Jason Tishler, Just van Rossum.