Python is my life !!!

پایتون

Python is my life !!!

پایتون

Python is my life !!!

برنامه نویس و طراح اپلیکیشن های تحت وب و مسلط به پایتون، جاوا اسکریپت، html، css، Angularjs و فریمورک Flask هستم ...

طبقه بندی موضوعی
بایگانی

اگر میخواستید در پایتون لیستی از اعداد 0 تا 10 داشته باشید از چه روشی استفاده میکردید؟

احتمالا از روش زیر:

>>> my_list = []
>>> for i in range(10):
...     my_list.append(i)
... 
>>> my_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

در این روش ابتدا یک متغییر از نوع لیست ایجاد میکنیم و سپس در یک حلقه هر کدام از اعداد 0 تا 9 را به لیست به کمک متد append اضافه میکنیم.

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

>>> my_list = [i for i in range(10)]
>>> my_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

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

>>> [i * 2 for i in range(10)]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

حتی میتوانید از شروط درون خطی هم در حلقه های درون خطی استفاده نمایید:

>>> [i * 2 for i in range(10) if i % 2 == 0]
[0, 4, 8, 12, 16]
>>> [i * 2 if i % 2 == 0 else i for i in range(10)]
[0, 1, 4, 3, 8, 5, 12, 7, 16, 9]

یا حتی میتوانید حلقه های تو در تو ایجاد کنید:

>>> [i * j for i in range(4) for j in range(4)]
[0, 0, 0, 0, 0, 1, 2, 3, 0, 2, 4, 6, 0, 3, 6, 9]

و یا به کمک حلقه های تو در تو لیست های چند بعدی ایجاد کنید:

>>> [[i * j for j in range(4)] for i in range(4)]
[[0, 0, 0, 0], [0, 1, 2, 3], [0, 2, 4, 6], [0, 3, 6, 9]]

ضمن اینکه باید مراقب باشید که استفاده از حلقه های درون خطی و شروط درون خطی باعث طولانی شدن یک خط از کدهای شما نشود چون زیبایی کدها را از بین برده و باعث پیچیدگی و غیرقابل فهم شدن آنها خواهد شد.

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

  • Saeid

در پایتون برای ایجاد یک شرط دو روش وجود دارد:

روش اول:

>>> x = 1
>>> y = 2
>>> if x == y:
...     res = 'Yes'
... else:
...     res = 'No'
... 
>>> res
'No'

روش دوم:

>>> x = 1
>>> y = 2
>>> res = 'Yes' if x == y else 'No'
>>> res
'No'

برای فهم بهتر از مثالی ساده تر استفاده میکنم، در حقیقت این شرط به این معنا می باشد که True را print کن اگر شرط برقرار باشد در غیر این صورت False را print کن.

>>> print(True if True else False)
True

در شروط درون خطی شما نمی توانید از elif استفاده نمایید و اگر نیاز به استفاده از elif بود به جای آن میتوانید از روش زیر استفاده نمایید:

>>> x = 1
>>> y = 2
>>> '=' if x == y else '<' if x < y else '>'
'<'

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

  • Saeid

حتما تا به حال موقع print خروجی برنامه های پایتون در یک فایل text به این مشکل برخورده اید که تمام خروجی برنامه یک جا باهم بعد از اتمام اجرای برنامه در فایل خروجی print میشود. این مشکل بیشتر در برنامه هایی به چشم میاید که قرار نیست هیچوقت به پایان برسند و همیشه در حال اجرا خواهند بود و یا اتمام آنها مدت زمان زیادی طول خواهد کشید.

پایتون نوشتن در stdout را cache می‌کند، این به این معنا است که برای بالا بردن سرعت هر بار که متنی print میشود آن را در stdout نمی نویسد و در نهایت در انتهای پروسس همه ی متن های print شده را یکجا باهم در stdout می نویسد. اینگونه اینکار از این که بخواهد یکی یکی بنویسد سریعتر انجام میشود، اما برای حل این مشکل چندین راه حل وجود دارد.

اگر پیش از این اینگونه عمل print را انجام می دادید:

print('Hello World !!!')

برای حل این مشکل کافی است print را به این صورت انجام دهید:

print('Hello World !!!', flush=True)

و یا به جای استفاده از تابع print از ماژول sys کمک بگیرید:

import sys
sys.stdout.write('Hello World !!!\n')
sys.stdout.flush()

اما توصیه میشود بدون ایجاد تغییر در کدهایتان برای حل این مشکل تنها برنامه ی پایتون را به این صورت اجرا نمایید:

python3 -u app.py

و یا اینکه با یکبار وارد کردن دستور زیر در command line دیگر لازم نیست تغییری در کدهایتان بدهید و میتوانید هم به همان شیوه ی سابق برنامه را اجرا نمایید:

export PYTHONUNBUFFERED=1
python3 app.py
  • Saeid

در این آموزش یاد خواهیم گرفت که چطور پروسس ها را در اوبونتو کنترل و مدیریت کنیم اما اگر از سایر توزیع های لینوکس استفاده میکنید نگران نباشید چون تفاوت چندانی با سایر توزیع های لینوکس ندارد، برای انجام این کار از supervisor استفاده خواهیم کرد، در حقیقت نام supervisor بسیار با قابلیت های آن سازگار است، برای مثال اگر سرور شما به صورت ناگهانی ریستارت شود بعد از شروع مجدد سرور به کار، supervisor به سرعت پروسس مورد نظر شما را دوباره اجرا خواهد کرد یا شما میتوانید آن را به صورتی تنظیم نمایید که اگر پروسس شما به هر دلیلی متوقف شد بدون اینکه شما اینکار را انجام دهید supervisor مجددا برنامه ی شما را Run کند.

سراغ نصب و اجرای supervisor می رویم، برای استفاده از supervisor ابتدا باید آن را نصب نمایید.

sudo apt-get install supervisor

در مرحله ی بعد virtualenv را نصب می نماییم (اختیاری):

sudo apt-get install virtualenv

در این مرحله فایلی به نام start.sh ساخته و آن را در مسیر فرضی root/start.sh را ذخیره میکنیم و محتویاتی مشابه محتویات زیر در آن قرار خواهیم داد، شما میتوانید بر اساس موارد مورد نیاز خود اطلاعات این فایل را ویرایش نمایید.

#!/bin/bash
echo 'Activating virtual env...'
. /root/.venv/bin/activate
echo 'Staring project'
python3 /root/app.py
echo 'Project running'

در خط سوم ابتدا virtualenv فعال شده و در خط پنجم برنامه مورد نظر ما اجرا خواهد شد و بقیه خطوط که ابتدای آن ها echo قرار داده شده به معنای چاپ کردن خطوط مورد نظر است تا در خروجی نمایش داده شوند.

سپس یک کد پایتون با محتویات زیر به نام app.py در همان مسیر ایجاد می کنیم:

from time import sleep
print('Runing my app')
num = 0
while True:
    sleep(3)
    print('num:', i)
    num += 1

همانطور که می بینید کد مورد نظر از یک حلقه ی بی نهایت تشکیل شده است که هر سه ثانیه عددی را چاپ می کند.

سپس به مسیر زیر رفته و فایلی به نام myapp.conf (نام فایل اختیاری است) می سازیم:

cd /etc/supervisor/conf.d/
sudo nano myapp.conf

و محتویات زیر را در آن قرار می دهیم:

[program:myapp]
command=/bin/bash /root/start.sh
autostart=true
autorestart=true
startretries=3
stderr_logfile=/root/myapp.err.log
stdout_logfile=/root/myapp.out.log

 

  1. نام برنامه می باشد که ما از myapp استفاده کرده ایم و کاملا اختیاری است.
  2. دستوری که برنامه ی مورد نظر ما را اجرا می کند.
  3. دو حالت true و false دارد و اگر true باشد با بوت شدن سیستم عامل پروسس مورد نظر به صورت اتوماتیک اجرا می شود.
  4. دو حالت true و false دارد و اگر true باشد در صورت وجود مشکل پروسس مورد نظر به صورت اتوماتیک دوباره اجرا می شود.
  5. تعداد تلاش هایی که درصورت ناموفق بودن اجرای برنامه انجام می شود.
  6. مسیر فایلی که error های برنامه در آن نوشته میشود.
  7. مسیر فایلی که خروجی برنامه در آن نوشته میشود.

سپس دستورات زیر را وارد نمایید:

sudo supervisorctl reread
sudo supervisorctl update

در آخر برای چک کردن خروجی برنامه میتوانید از دستور زیر:

sudo supervisorctl tail -f myapp stdout

و برای مشاهده error های برنامه از این دستور استفاده نمایید:

sudo supervisorctl tail -f myapp stderr

در صورت مشکل و نمایش داده نشدن خروجی برنامه (قسمت های print شده) در stdout میتوانید مطلب زیر را مطالعه نمایید:
حل مشکل print خروجی برنامه های پایتون در stdout

 

  • Saeid

در ابتدا باید این را بدانید که رشته ها در پایتون غیرقابل تغییر می باشند و تغییر یک کاراکتر از یک رشته در پایتون به سادگی انجام این کار در یک لیست نیست.

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

برای درک بهتر ابتدا همین کار را در یک لیست انجام می دهیم:

>>> my_list = ['a', 'b', 'c', 'd']
>>> my_list[2] = 'e'
>>> my_list
['a', 'b', 'e', 'd']

دیدید که در لیست به سادگی میتوان این کار را انجام داد اما اگر همین اعمال را برای رشته ها انجام دهید با TypeError مواجه خواهید شد:

>>> my_str = 'abcd'
>>> my_str[2] = 'e'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

برای انجام چنین کاری روش های متفاوتی وجود دارد که در این پست به دو روش اشاره خواهیم کرد.

روش اول:

در این روش ابتدا رشته ی مورد نظر را به لیست تبدیل کرده و سپس بر اساس ایندکس کاراکتر مورد نظر آن را تغییر می دهیم و در آخر به کمک متد join لیست را به یک استرینگ تبدیل می کنیم.

>>> my_str = 'abcd'
>>> my_list = list(my_str)
>>> my_list[2] = 'e'
>>> my_str = ''.join(my_list)
>>> my_str
'abed'

روش دوم:

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

>>> my_str = 'abcd'
>>> my_str = my_str[:2] + 'e' + my_str[3:]
>>> my_str
'abed'

کدام یکی سریعتر است؟

روش اول:

>>> timeit.timeit("my_str = 'abcd'; my_list = list(my_str); my_list[2] = 'e'; my_str = ''.join(my_list)", number=10000000)
2.8461143329986953

روش دوم:

>>> timeit.timeit("my_str = 'abcd'; my_str = my_str[:2] + 'e' + my_str[3:]", number=10000000)
1.637490514000092

* با توجه به تست زمان در هر دو روش این موضوع اثبات میشود که روش دوم سریعتر از روش اول می باشد.

  • Saeid