درس ۱۰: فایل، ورودی و خروجی (I/O) در پایتون

فایل، ورودی و خروجی در پایتون - input, print, file

Photo by Mr Cup / Fabien Barral

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

سطح: مقدماتی



فایل‌ها

فایل‌ها (Files) جزو منابع منطقی کامپیوتر به شمار می‌روند، توسط سیستم عامل مدیریت می‌شوند و امکانی برای نگهداری طولانی مدت از اطلاعات می‌باشند. فایل‌ها در واقع بیت‌هایی متوالی از صفر و یک هستند که بر روی دیسک ذخیره گشته‌اند و معمولا در دو قالب جداگانه:

  • «فایل‌‌ باینری» (binary file) - مانند: فایل‌های ویدئو، فایل‌های تصویر، فایل zip، فایل بایت‌کد پایتون و...

  • «فایل‌ متنی» (text file) - مانند: فایل HTML، فایل ماژول پایتون و...

شناخته می‌شوند.

همانطور که گفته شد فایل‌ها چیزی جز مجموعه‌ای از مقدارهای باینری (یا دودویی) نیستند و فایل‌های متنی نیز در واقع یک زیر مجموعه از فایل‌های باینری است با این تفاوت که بیت‌های یک فایل متنی در کنار هم، بسته به نوع کدگذاری آن متناظر با دنباله‌ای از کاراکترهایی مشخص و قابل چاپ هستند. محتوای این نوع فایل در سطرهایی جداگانه قرار داده می‌شود و با استفاده از برنامه‌های ویرایشگر متن برای انسان خوانا می‌باشد. در یک فایل متنی با کدگذاری ASCII (اَسکی) هر هشت بیت (یک بایت) برابر یک کاراکتر می‌باشد - کدهای اسکی هفت بیتی هستند ولی در اکثر کامپیوترها برای هر کدام یک بایت در نظر گرفته می‌شود - برای نمونه کلمه Python به شکل شش بایت که هر کدام به ترتیب برابر مقدار باینری کد اسکی هر یک از این کاراکترها می‌باشد، ذخیره می‌شود. اسکی تنها از ۱۲۸ کاراکتر - از کد ۰ تا ۱۲۷ (در پایه ده) - پشتیبانی می‌کند و به همین دلیل امروزه بیشتر از کدگذاری‌های استاندارد Unicode (یونیکد) استفاده می‌گردد. در یونیکد مجموعه بسیار بزرگتری از کاراکتر نسبت به کدگذاری اسکی پشتیبانی می‌شود به گونه‌ای که اسکی را نیز در برمی‌گیرد؛ برای نمونه در کدگذاری UTF-8 از این استاندارد، ۱۲۸ کد نخست (از کد ۰ تا ۱۲۷) برابر کد همان ۱۲۸ کاراکتر اسکی می‌باشد. کدگذاری UTF-8 کاراکترهای یونیکد را در یک دنباله بایت با طول متغیر (۱ تا ۴ بایت) ارايه می‌دهد؛ در این کدگذاری برای کاراکترهای اسکی تنها یک بایت در نظر گرفته می‌شود.

در یک فایل باینری وجود سطر مفهومی ندارد و بایت‌های آن ممکن است داده‌هایی را نمایش دهند که نمی‌توان آن‌ها را توسط هیچ یک از کدگذاری‌های کاراکتر (UTF-8 ،ASCII و...) چاپ کرد یا حتی ممکن است در صورت چاپ آن‌ها نیز حاصل برای انسان غیر قابل فهم باشد.

تابع open

پایتون یک نوع شی آماده برای دستیابی فایل‌ها در برنامه ارایه می‌دهد که این شی با استفاده از تابع آماده (open(file, mode [اسناد پایتون] ایجاد می‌گردد؛ آرگومان نخست یک شی رشته حاوی نام کامل فایل (نشانی + نام + پسوند) مورد نظر بر روی دیسک کامپیوتر است و آرگومان دوم نیز یک رشته با مقداری خاص است و حالتی که این فایل می‌بایست در آن باز شود را مشخص می‌سازد؛ این آرگومان اختیاری است و مقدار پیش‌فرض آن 'r' می‌باشد. برای نمونه به کدهای پایین که با یکدیگر معادل هستند توجه نمایید:

>>> f = open('/home/saeid/Documents/sample.txt')
>>> f = open('/home/saeid/Documents/sample.txt', 'r')
>>> f = open('/home/saeid/Documents/sample.txt', mode='r')

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

r'C:\Users\Saeid\Documents\sample.txt'
'C:\\Users\\Saeid\\Documents\\sample.txt'

آرگومان file را می‌توان تنها با نام خالی فایل و بدون ذکر مسیر آن مقداردهی کرد؛ در این صورت مفسر پایتون مسیر دایرکتوری جاری را برای آن در نظر می‌گیرد. با استفاده از تابع ()getcwd از ماژول os [اسناد پایتون] می‌توانیم مسیر دایرکتوری جاری برنامه را به دست آوریم. [در درس بعد بیشتر درباره این ماژول صحبت خواهیم کرد]:

>>> import os

>>> os.getcwd()
'/home/saeid'

آرگومان mode نیز بر حسب نیاز می‌تواند یکی از مقدارهای پایین را داشته باشد:

  • 'r': فایل در قالب متنی تنها به منظور خواندن از آن باز می‌شود و اشاره‌گر در ابتدای آن قرار می‌گیرد. چنانچه فایلی با این نام موجود نباشد یک خطا (یا استثنا) FileNotFoundError گزارش می‌گردد. معادل 'rt'

  • 'w': فایل در قالب متنی تنها به منظور نوشتن در آن باز می‌شود؛ متن درون آن (در صورت وجود) پاک می‌شود و اشاره‌گر در ابتدای آن قرار می‌گیرد. چنانچه فایلی با این نام موجود نباشد، ابتدا ایجاد و سپس باز می‌شود. معادل 'wt'

  • 'a': فایل در قالب متنی تنها به منظور افزودن متنی در انتهای متن موجود در آن باز می‌شود؛ اشاره‌گر در انتهای فایل قرار دارد. چنانچه فایلی با این نام موجود نباشد، ابتدا ایجاد و سپس باز می‌شود. معادل 'at'

  • 'x': فقط در پایتون exclusive creation) - 3x) فایل در قالب متنی ایجاد و به منظور نوشتن در آن باز می‌شود؛ چنانچه این فایل از پیش موجود باشد یک خطا (یا استثنا) FileExistsError گزارش می‌گردد. معادل 'xt'

  • 'rb' و 'wb' و 'ab' و 'xb': همان توضیح گزینه‌های مشابه بالا را دارند ولی با این تفاوت که برای کار با فایل‌هایی در قالب باینری استفاده می‌شوند.

  • '+r': فایل در قالب متنی به منظور خواندن و نوشتن باز می‌شود و اشاره‌گر در ابتدای آن قرار می‌گیرد. چنانچه فایلی با این نام موجود نباشد یک خطا (یا استثنا) FileNotFoundError گزارش می‌گردد. توجه داشته باشید که در این حالت عمل نوشتن از همان ابتدای فایل، باعث جایگزین شدن متن جدید با متن حاضر می‌شود. معادل '+rt' یا 'r+t'

  • '+w': فایل در قالب متنی به منظور نوشتن و خواندن باز می‌شود؛ متن درون آن (در صورت وجود) پاک می‌شود و اشاره‌گر در ابتدای آن قرار می‌گیرد. چنانچه فایلی با این نام موجود نباشد، ابتدا ایجاد و سپس باز می‌شود. معادل '+wt' یا 'w+t'

  • '+a': فایل در قالب متنی به منظور افزودن متنی در انتهای متن موجود در آن و همچنین خواندن باز می‌شود؛ اشاره‌گر در انتهای فایل قرار دارد. چنانچه فایلی با این نام موجود نباشد، ابتدا ایجاد و سپس باز می‌شود. معادل '+at' یا 'a+t'

  • '+x': فقط در پایتون 3x - فایل در قالب متنی ایجاد و به منظور نوشتن و خواندن باز می‌شود؛ چنانچه این فایل از پیش موجود باشد یک خطا (یا استثنا) FileExistsError گزارش می‌گردد. معادل '+xt' یا 'x+t'

  • '+rb' یا 'r+b' و '+wb' یا 'w+b' و '+ab' یا 'a+b' و '+xb' یا 'x+b': همان توضیح گزینه‌های مشابه بالا را دارند ولی با این تفاوت که برای کار با فایل‌هایی در قالب باینری استفاده می‌شوند.

  • 'rU': خواندن یک فایل متنی با پشتیبانی از Universal Newline. معادل 'rtU'

  • 'rbU': خواندن یک فایل باینری با پشتیبانی از Universal Newline.

که در آن‌ها:

  • r: خواندن (read)

  • w: نوشتن (write)

  • a: درج در انتها (appending)

  • t: تعیین قالب متنی (text) برای فایل مورد نظر؛ قالب پیش‌فرض است و نیازی به درج آن نیست

  • b: تعیین قالب باینری (binary) برای فایل مورد نظر

  • +: فایل به منظور بروز رسانی (updating) باز می‌شود

  • U: حالت Universal Newline

در قرارداد سیستم‌های عامل گوناگون از رشته‌های مختلفی - که می‌تواند از یک یا چند کاراکتر تشکیل شده باشد - برای نشانه‌گذاری انتهای سطرهای یک فایل متنی استفاده شده است؛ برای نمونه در ویندوز از CRLF (یا 'r\n\') و در گنولینوکس از LF (یا 'n\') استفاده می‌شود. شی فایل پایتون به صورت پیش‌فرض از همان قرارداد سیستم عامل میزبان برای تعیین رشته Newline خود استفاده می‌کند؛ ولی چنانچه قصد دارید در پایتون فایلی با قرارداد سیستم عامل دیگری را به منظور خواندن باز نمایید می‌بایست این کار را در حالت Universal Newline انجام دهید. در این حالت به هنگام خواندن از یک فایل، پایتون تمام رشته‌های Newline موجود در فایل را به کاراکتر 'n\' نگاشت می‌کند [PEP 278]؛ دستور os.linesep [اسناد پایتون] رشته Newline سیستم عامل میزبان را برمی‌گرداند:

>>> import os

>>> os.linesep  # GNU/Linux
'\n'

باز کردن یک فایل به منظور خواندن از آن حکم یک منبع ورودی (input) و باز کردن یک فایل به منظور نوشتن در آن حکم یک منبع خروجی (output) را در برنامه دارد.

تابع ()open آرگومان‌های اختیاری دیگری نیز دارد که برای بررسی آن‌ها می‌توانید به اسناد پایتون مراجعه نمایید.

متدهای شی فایل پایتون

  • (write(string: یک شی از نوع str یا bytes را دریافت می‌کند و آن را درون شی فایل مورد نظر می‌نویسد:

    >>> text = '1) Python\n2) Programming\n3) Language\n'
    
    >>> print(text)
    1) Python
    2) Programming
    3) Language
    
    >>>
    
    >>> type(text)
    <class 'str'>
    
    >>> output = open('textfile.txt', 'w')
    >>> output.write(text)
    37
    >>> output.close()
    

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

    >>> output = open('binaryfile.bin', 'wb')
    >>> output.write(text)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: a bytes-like object is required, not 'str'
    

    نمی‌توان از شی str برای نوشتن در فایلی که در حالت باینری باز شده است استفاده کرد.

    >>> data = '1) Python\n2) Programming\n3) Language\n'
    
    >>> # Convert str to bytes
    >>> bdata = bytes(data, 'utf-8')
    
    >>> bdata
    b'1) Python\n2) Programming\n3) Language\n'
    
    >>> type(bdata)
    <class 'bytes'>
    
    
    >>> output = open('binaryfile.bin', 'wb')
    >>> output.write(bdata)
    37
    >>> output.close()
    

    در رفتار گنولینوکس تفاوتی بین حالت متنی و باینری وجود ندارد؛‌ اکنون اگر هر دو فایل textfile.txt و binaryfile.bin را (در گنولینوکس) توسط برنامه ویرایشگر متن باز نمایید، خواهید دید که محتوای این دو فایل مشابه یکدیگر نمایش داده می‌شوند.

    در گنولینوکس، باز کردن فایل textfile.txt توسط یک برنامه ویرایشگر متن:

    11) Python
    22) Programming
    33) Language
    

    در گنولینوکس، باز کردن فایل binaryfile.bin توسط یک برنامه ویرایشگر متن:

    11) Python
    22) Programming
    33) Language
    

    ولی در ویندوز به هنگام حالت متنی، اگر یک فایل را به منظور خواندن باز نمایید کاراکترهای 'n\' موجود در آن به شکل 'r\n\' برگردانده می‌شوند و اگر که یک فایل را به منظور نوشتن باز کنید، هر بار رشته 'r\n\' به جای 'n\' نوشته می‌شود. در حالت باینری این کارها انجام نمی‌شود.

    اگر دستورهای یاد شده را در ویندوز اجرا نماییم؛ دو فایل مورد نظر با محتوای پایین توسط برنامه ویرایشگر متن نمایش داده خواهند شد.

    در ویندوز، باز کردن فایل textfile.txt:

    11) Python
    22) Programming
    33) Language
    

    در ویندوز، باز کردن فایل binaryfile.bin:

    11) Python2) Programming3) Language
    
  • ()close: پس از پایان کار با هر فایل، می‌بایست آن را ببندید؛ این متد فایل باز شده را می‌بندد. شی فایل مورد نظر پس از فراخوانی این متد، هیچ متد دیگری را نمی‌تواند فراخوانی کند.

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

    همچنین برای بررسی اینکه یک فایل باز است یا اینکه بسته شده است می‌توانید از صفت closed استفاده نمایید؛ این صفت در صورتی که فایل بسته شده باشد حاوی مقدار True می‌باشد:

    >>> f.closed
    False
    
    >>> f.close()
    
    >>> f.closed
    True
    
  • ()read: تمام محتوای فایل را می‌خواند و در قالب یک شی از نوع str (برای فایل‌های متنی) یا bytes (برای فایل‌های باینری) برمی‌گرداند:

    >>> input = open('textfile.txt')
    
    >>> content = input.read()
    
    >>> input.close()
    
    >>> type(content)
    <class 'str'>
    
    >>> content
    '1) Python\n2) Programming\n3) Language\n'
    
    >>> print(content)
    1) Python
    2) Programming
    3) Language
    
    >>>
    
    >>> # Reading a binary file
    
    >>> input = open('binaryfile.bin', 'rb')
    
    >>> content = input.read()
    
    >>> input.close()
    
    >>> type(content)
    <class 'bytes'>
    
    >>> content
    b'1) Python\n2) Programming\n3) Language\n'
    
    >>> print(content)
    b'1) Python\n2) Programming\n3) Language\n'
    >>>
    

    این متد یک آرگومان اختیاری نیز دارد؛ این آرگومان یک عدد صحیح است که تعداد کاراکتر (یا بایت) که می‌بایست از فایل خوانده و برگردانده شوند را تعیین می‌کند:

    >>> f = open('textfile.txt')
    
    >>> f.read(5)
    '1) Py'
    
    >>> f.read(5)
    'thon\n'
    
    >>> f.read(10)
    '2) Program'
    
    >>> f.read(4)
    'ming'
    
    >>> f.read(1)
    '\n'
    
    >>> f.close()
    

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


  • ()readline: در هر فراخوانی یک سطر از فایل - تا رشته Newline - را برمی‌گرداند:

    >>> f = open('textfile.txt')
    
    >>> f.readline()
    '1) Python\n'
    
    >>> f.readline()
    '2) Programming\n'
    
    >>> f.readline()
    '3) Language\n'
    
    >>> f.readline()
    ''
    
    >>> f.close()
    
  • ()readlines: تمام سطرهای یک فایل را در قالب یک شی لیست بر می‌گرداند:

    >>> f = open('textfile.txt')
    
    >>> cl = f.readlines()
    
    >>> cl
    ['1) Python\n', '2) Programming\n', '3) Language\n']
    
    >>> cl[1]
    '2) Programming\n'
    
    >>> f.close()
    
  • (writelines(list: یک شی لیست که تمام اعضای آن از نوع str هستند را به عنوان آرگومان گرفته و اعضای آن را به ترتیب در فایل مورد نظر می‌نویسد:

    >>> L = ['a', 'b', 'c', 'd\n', 'e']
    
    >>> f = open('tf.txt', 'w')
    >>> f.writelines(L)
    >>> f.close()
    

    حاصل کد بالا؛ باز کردن فایل tf.txt توسط یک برنامه ویرایشگر متن:

    1abcd
    2e
    
  • (seek(offset: آرگومان offset یک عدد صحیح است و این متد موقعیت اشاره‌گر فایل را به آن offset نسبت به ابتدای فایل تغییر می‌دهد:

    >>> f = open('textfile.txt')
    
    >>> f.seek(3)
    3
    
    >>> f.read(6)
    'Python'
    
    >>> f.close()
    
  • ()flush: باعث ذخیره محتوای بافر در فایل می‌شود.

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

دستور for

از تابع ()open نیز می‌توان در حلقه for استفاده کرد؛ در این صورت در هر بار تکرار سطرهای فایل پیمایش می‌شوند:

>>> for line in open('textfile.txt'):
...     print(line, end='')
...
1) Python
2) Programming
3) Language
>>>

از آنجا که متن درون فایل خود حاوی Newline (در اینجا: 'n\') است، آرگومان end تابع ()print را برای جلوگیری از درج 'n\' در انتهای هر سطر تغییر دادیم [در بخش print درباره آرگومان end صحبت خواهیم کرد].

دستور with/as

یک دستور مرکب است که از اشیایی که با نوع ”Context Manager“ [اسناد پایتون] در پایتون شناخته می‌شوند، پشتیبانی می‌کند [PEP 343]. برخی از اشیا در پایتون - به مانند شی فایل - قابلیتی با نام ”Context Manager“ دارند؛ برای پیاده سازی این قابلیت، کلاس شی مورد نظر می‌بایست حاوی دو متد ویژه ()__enter__ و ()__exit__ باشد که به ترتیب در زمان‌های «ورود به» و «خروج از» بدنه دستور with/as فراخوانی می‌شوند. [این نوع شی به صورت کامل‌تر توسط درس بیست و یکم برسی خواهد شد.]

دستور with/as ساختاری مشابه پایین دارد:

with expression as variable:
    statement(s)

در این ساختار، expression نماد بخشی از دستور است که یک شی از نوع Context Manager را برمی‌گرداند؛ این شی با استفاده از کلمه کلیدی as به یک متغیر ارجاع داده می‌شود. برای نمونه ساختار with/as مربوط به یک شی فایل در پایین نوشته شده است:

with open('textfile.txt', 'w') as output:
    output.write('text')

پس از ایجاد شی فایل، این شی می‌بایست وارد اجرای دستور with/as شود؛ with/as این کار را با فراخوانی متد ()__enter__ انجام می‌دهد. در واقع این متد همان شی فایل ایجاد شده را برمی‌گرداند که در ادامه توسط as به متغیر output ارجاع داده می‌شود. همچنین با استفاده از این ساختار دیگر نیازی به فراخوانی متد ()close برای شی فایل نمی‌باشد؛ چرا که این کار پس از پایان دستورهای بدنه با فراخوانی شدن متد ()__exit__ توسط with/as به انجام می‌رسد؛ در واقع with/as بستن فایل را در پایان اجرای دستورهای بدنه خود تضمین می‌کند. همچنین در این ساختار چنانچه هنگام کار با فایل خطایی (یا استثنایی) رخ دهد، پیش از گزارش آن، ابتدا فایل بسته خواهد شد.

توجه داشته باشید که یک شی فایل همیشه باید بسته شود؛ در مواقعی که قصد استفاده از حلقه for برای یک شی فایل را دارید بهتر است از آن درون ساختار with/as بهره بگیرید:

with open('textfile.txt') as f:
    for line in f:
        print(line)

از دستور with/as می‌توان به شکل تودرتو نیز بهره گرفت:

with A() as a:
    with B() as b:
        statements

همچنین از نسخه 3.1 به بعد پایتون سینتکس جدیدی افزوده شده است که توسط آن می‌توان همزمان از چند Context Manager بهره گرفت:

with A() as a, B() as b:
    statements

به مانند نمونه کد پایین که دو فایل را باز می‌کند؛ از یکی می‌خواند و برخی از سطرهای آن را در فایل دیگر می‌نویسد:

with open('data') as fin, open('res', 'w') as fout:
    for line in fin:
        if 'key' in line:
            fout.write(line)

شی فایل استاندارد

سه نوع شی فایل توسط مفسر پایتون ایجاد می‌گردد که هر سه آن‌ها توسط ماژول sys در دسترس هستند:

  • sys.stdin: ورودی استاندارد [اسناد پایتون]؛ برای دستیابی تمامی ورودی‌ها در حالت تعاملی پایتون - مانند فراخوانی تابع ()input - از این شی استفاده می‌گردد.

  • sys.stdout: خروجی استاندارد [اسناد پایتون]؛ توسط print مورد استفاده قرار می‌گیرد.

  • sys.stderr: خطا استاندارد [اسناد پایتون]؛ شی‌ای است که خطاها را دریافت می‌کند.

نه همیشه ولی می‌توان منبع sys.stdin را صفحه‌کلید کامپیوتر و منبع sys.stdout و sys.stderr را نیز صفحه‌نمایش در نظر گرفت.

تابع ()input

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

تابع ()input [اسناد پایتون] یک سطر از کاربر را می‌خواند و در قالب یک شی از نوع str برمی‌گرداند:

>>> s = input()

با اجرا دستور، مفسر پایتون منتظر ورود متن می‌ماند - در این نمونه متن Hello Python با استفاده از صفحه‌کلید، تایپ می‌شود - سپس با فشردن کلید Enter، پایان ورود داده اعلام و سپس مفسر پایتون تمام کاراکترهای دریافتی را در قالب یک شی رشته - نوع str - به متغیر s ارجاع می‌دهد:

>>> s
'Hello Python'
>>> type(s)
<type 'str'>

همچنین می‌توان متنی را برای مشاهده کاربر به صورت آرگومان در فراخوانی تابع قرار داد:

>>> s = input("What's your name? ")
What's your name? Alan

>>> s
'Alan'
>>> s = input("How old are you? ")
How old are you? 41

>>> s
'41'
>>> type(s)
<type 'str'>

اکنون زمان خوبی است تا با یکی دیگر از تابع‌های آماده در پایتون آشنا شویم. ()eval [اسناد پایتون] تابع آماده دیگری در پایتون است که یک شی رشته را دریافت و متن آن را به شکل کد پایتون تفسیر می‌کند:

>>> x = 1
>>> y = eval('x + 1')
>>> y
2
>>> type(y)
<type 'int'>

به نمونه کدهای پایین نیز توجه نمایید:

>>> eval("9 // 2")
4

>>> eval("9 /// 2")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    9 /// 2
        ^
SyntaxError: invalid syntax
>>>
>>> a = '32'
>>> type(a)
<type 'str'>

>>> b = eval(a)

>>> b
32
>>> type(b)
<type 'int'>
>>> print eval("__import__('os').getcwd()")
/home/saeid

تابع ()__import__ [اسناد پایتون] عملکردی برابر با دستور import دارد ولی با این تفاوت که می‌توان از آن به شکلی پویا در طی اجرای برنامه برای وارد کردن ماژول‌های گوناگون استفاده نمود؛ در این حالت نام یک ماژول حتی می‌تواند به شکل یک متغیر در آرگومان تابع قرار بگیرد.

برای تفریح، اکنون می‌توانید تنها با یک خط کد پایین یک ماشین‌حساب ساده ایجاد کنید :)

print(eval(input("Type your formula: ")))
Type your formula: 2 * 5 + 30 / 2
25.0

تابع ()print

پیش‌تر با تابع ()print پایتون آشنا هستیم ولی در اینجا می‌خواهیم کمی بیشتر آن را بررسی نماییم. این تابع [اسناد پایتون]؛ الگویی به شکل پایین دارد:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
  • objects*: بیانگر اشیایی است می‌خواهیم در خروجی قرار بدهیم. که می‌تواند هیچ باشد - که برابر نمایش یک سطر خالی است - یا اینکه می‌تواند یک یا چند شی - که در این صورت اشیا می‌بایست توسط یک کاما , از یکدیگر جدا شوند - را در برگیرد:

    >>> print()
    
    >>>
    
    >>> s = 'Python'
    
    >>> print(s)
    Python
    
    >>> print(s, '3x')
    Python 3x
    
    >>> print(4 * 5 / 2, 3 * 3)
    10.0 9
    
  • sep: رشته‌ای که می‌بایست بین اشیا قرار گیرد را تعیین می‌کند. مقدار این آرگومان در حالت پیش‌فرض یک حرف فاصله (یک کلید Space) است. مقدار ارسالی به این آرگومان می‌بایست یک شی رشته یا None باشد:

    >>> print(s, '3x', sep='-')
    Python-3x
    
    >>> print(s, '3x', sep=None)
    Python 3x
    
  • end: رشته‌ای که می‌بایست در انتهای هر سطر قرار گیرد را تعیین می‌کند. مقدار این آرگومان در حالت پیش‌فرض 'n\' است. مقدار ارسالی به این آرگومان می‌بایست یک شی رشته یا None باشد:

    >>> for a in range(5):
    ...     print(a)
    ...
    0
    1
    2
    3
    4
    >>>
    
    
    >>> for a in range(5):
    ...     print(a, end=' ')
    ...
    0 1 2 3 4 >>>
    
  • file: خروجی را تعیین می‌کند که می‌بایست یک شی به همراه متد (write(string درون کلاس خود، باشد. این آرگومان به صورت پیش‌فرض بر روی خروجی استاندارد مقداردهی شده است. این تابع قابلیت استفاده در حالت باینری فایل‌ها را ندارد:

    >>> output = open('textfile.txt', 'w')
    
    >>> print('Hi :)', file=output)
    
    >>> output.close()
    
  • flush: این آرگومان از نسخه 3.3 به تابع ()print پایتون افزوده شده است. هنگامی که خروجی بر روی یک فایل قرار گرفته باشد؛ با تنظیم این گزینه بر روی مقدار True، عمل انتقال متن به فایل بدون اتلاف وقت انجام می‌پذیرد.

ساختارهای ذخیره و تبادل داده

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

XML

ساختار Extensible Markup Language یا همان XML [ویکی‌پدیا] یکی از با سابقه‌ترین نوع از ساختار تبادل داده در علم رایانش است. این ساختار بر اساس node یا elementهای تو در تو ایجاد می‌گردد. از این ساختار بیشتر برای ذخیره پارامترهای پیکربندی یا تبادل داده در برخی پرتکل‌ها به مانند SOAP [ویکی‌پدیا] استفاده می‌شود. به نمونه فایل زیر توجه نمایید:

<students>
   <student>
       <name>John</name>
       <family>Doe</family>
       <age>21</age>
       <gender>Male</gender>
       <final_grade>87</final_grade>
   </student>
   <student>
       <name>Jane</name>
       <family>Smith</family>
       <age>19</age>
       <gender>Female</gender>
       <final_grade>95</final_grade>
   </student>
   <student>
       <name>Tom</name>
       <family>Lee</family>
       <age>20</age>
       <gender>Male</gender>
       <final_grade>78</final_grade>
   </student>
</students>

در این مثال اطلاعات مربوط به سه دانش آموز سازماندهی شده است. XML از elementهای تودرتو ایجاد می‌گردد، هر element شروع <element_name> و پایان <element_name/> مشخصی دارد و می‌تواند حاوی یک داده یا یک (یا چند - لیست) element دیگر باشد. فضاهای خالی و نظم تورفتگی‌ها اهمیتی ندارد و تنها برای خوانایی بیشتر استفاده شده است.

در پایتون می‌توان به سادگی با استفاده از ماژول xml.etree.ElementTree [اسناد پایتون] از کتابخانه استاندارد آن، با این نوع فایل کار کرد. البته ابزارهای دیگری نیز توسط دیگر کاربران پایتون توسعه داده شده است که در صورت نیاز یا علاقه می‌توانید با کمی جستجو آنها را بیابید.

CSV

ساختار Comma-Separated Values یا CSV [ویکی‌پدیا] داده‌ها را مانند یک جدول سازماندهی می‌کند که داده‌های موجود در هر سطر آن با استفاده از یک کاراکتر کاما یا , از یکدیگر تفکیک شده‌اند. این ساختار در موارد ذخیره اطلاعات یا گزارش‌ها بر روی فایل بسیار رایج است. به نمونه فایل زیر توجه نمایید:

name,family,age,gender,final_grade
John,Doe,21,Male,87
Jane,Smith,19,Female,95
Tom,Lee,20,Male,78

سطر یکم، سرآیند (Header) اختیاری است.

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

JSON

ساختار JavaScript Object Notation یا JSON [ویکی‌پدیا] در تبادل داده بسیار رایج است. به خصوص در پیاده‌سازی سرویس‌ها [REST API]. این ساختار، داده‌ها را به شکل کلید:مقدار سازماندهی می‌کند و کاملا شبیه به ساختار شی دیکشنری در پایتون است. به نمونه فایل زیر توجه نمایید:

[
   {
       "name": "John",
       "family": "Doe",
       "age": 21,
       "gender": "Male",
       "final_grade": 87
   },
   {
       "name": "Jane",
       "family": "Smith",
       "age": 19,
       "gender": "Female",
       "final_grade": 95
   },
   {
       "name": "Tom",
       "family": "Lee",
       "age": 20,
       "gender": "Male",
       "final_grade": 78
   }
]

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

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



😊 امیدوارم مفید بوده باشه