10 نصائح مفيدة لكتابة سكريبت بايثون

في هذه المقالة، سأقدم لك بعض النصائح والحيل الخاصة بـبايثون إلى جانب أمثلة سكريبتات لمساعدتك في تحقيق أقصى استفادة من بايثون.

أولاً، دعنا نحدد ما هو السكريبت في بايثون. هو مجموعة من التعليمات المكتوبة بلغة بايثون لطلب من الكمبيوتر تنفيذ بعض المهام.

قبل أن نبدأ بنصائح بايثون، تأكد من فهمك لهياكل بيانات بايثون أولاً. إذا لم تكن على دراية بها، ففكر في الالتحاق بدورة هياكل بيانات بايثون. ستمنحك فرصة العمل مع القوائم والقوائم المتداخلة والمجموعات والقواميس.

في هذه المقالة، سنبدأ بحالة استخدام بسيطة ونعمل على تحسين السكريبت الخاص بنا أثناء تنفيذ النصائح المختلفة لكتابة سكريبت بايثون مفيد.

10 نصائح مفيدة لتحسين سكريبت بايثون

في البداية، سنكتب سكريبت يقرأ صورة RGB ويحولها إلى تدرج الرمادي، وهي خطوة معالجة أولية أساسية في الرؤية الحاسوبية. سنستخدم OpenCV لهذه الخطوة. إذا لم يكن لديك OpenCV مثبتًا، فيمكنك القيام بذلك بسهولة باستخدام pip:

pip install opencv-python

بالنسبة لهذا المثال، قمت بتنزيل 50 صورة لسيارات الفورمولا المحفوظة في data/formula_one مع ملفات من 000000.jpg إلى 000049.jpg.

أولاً، لنقم بإنشاء ملف بايثون يسمى gray.py ونقوم بتنفيذه في الطرفية. سيقوم بقراءة الصور وتحويلها إلى تدرج الرمادي وعرضها على شاشتنا.

import cv2
import glob
 
image_files = sorted(glob.glob("./data/formula_one/*.jpg"))
 
for i in image_files:
   img = cv2.imread(i)
   gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
   gray_img_small = cv2.resize(gray_img, (960, 540))
   cv2.imshow('Grayscale Image', gray_img_small)
   cv2.waitKey(0)
 
cv2.destroyAllWindows()

وفيما يلي مثال على النتائج:

الآن بعد أن أصبح لدينا شيء قيد التشغيل، دعنا نرى كيف يمكننا تحسين هذا السكريبت باستخدام النصيحة الأولى.

التأكيد على قابلية قراءة كود بايثون

نصيحتي الأولى هي عدم كتابة البرامج النصية لنفسك، حتى لو كنت الشخص الوحيد الذي يستخدمها. بدلاً من ذلك، فكر في نفسك في المستقبل – أو، إذا كتبت كود بايثون لشخص آخر، فكر في الشخص الذي سيحافظ على الكود بعدك. بعبارة أخرى، يجب أن يكون الكود مُعلَّقًا عليه جيدًا وقابلًا للقراءة ومفهومًا من قبل أي شخص سيطلع على سكريبت بايثون الخاص بك. إذا قررت الإفراط في هندسة الكود وجعله مُحسَّنًا للغاية على حساب قابلية القراءة، فيجب أن تكون دقيقًا في تعليقاتك.

لم أضع أي تعليقات في المثال السابق، لذا يمكن أن تكون هذه هي الخطوة الأولى لتحسين سكريبت بايثون. دعنا نستخدم التعليقات لشرح ما يفعله الكود:

import cv2
import glob
 
# Load the images in ascending order
image_files = sorted(glob.glob("./data/formula_one/*.jpg"))
 
# Loop through the files display them as grayscale
for i in image_files:
   img = cv2.imread(i)  # Read the image
   gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Convert the image to grayscale
   gray_img_small = cv2.resize(gray_img, (960, 540)) # Resize the image for visualization purpose
   cv2.imshow('Grayscale Image', gray_img_small) # Display the gray image in a window called 'Grayscale Image'
   cv2.waitKey(0) # Press any key to close the window
   
cv2.destroyAllWindows() # Close all the open windows

الآن أصبح الكود أكثر وضوحًا. لاحقًا، ستساعدك هذه التعليقات على تذكر عملية التفكير الخاصة بك عند كتابة الكود. ومع ذلك، قد تكون تعليقاتنا واضحة بعض الشيء، حيث أن هذه المقالة عبارة عن برنامج تعليمي حول نصائح وحيل بايثون. في هذا السياق، غالبًا ما تشرح التعليقات “ماذا يفعل” الكود؛ بدلاً من ذلك، غالبًا ما يكون من الجيد كتابة “لماذا” لهذا المقطع من الكود. على سبيل المثال، كان بإمكاني كتابة التعليقات على هذا النحو:

import cv2
import glob
 
# Sorting the images in order is essential when the images are recorded in sequences (i.e., videos, sensor capture with timestamps)
# This is particularly important if the images are video frames, where the order matters.
image_files = sorted(glob.glob("./data/formula_one/*.jpg"))
 
# Converting to grayscale normalizes images and makes image processing faster. It helps machine learning models when color is not an important feature.
for i in image_files:
   img = cv2.imread(i)
   gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
   gray_img_small = cv2.resize(gray_img, (960, 540))
   cv2.imshow('Grayscale Image', gray_img_small)
   cv2.waitKey(0) 
 
cv2.destroyAllWindows()

اكتب دوال بايثون قابلة لإعادة الاستخدام

إذا كان بوسعك جعل الكود قابلاً لإعادة الاستخدام بالكامل بمساعدة الدوال، فسوف توفر على نفسك الكثير من المتاعب. لذا، بدلاً من كتابة التعليمات مباشرة في ملفك، حاول تضمينها داخل الدوال. سيجبرك هذا على تعميم الكود وجعله أكثر قابلية لإعادة الاستخدام في السكريبتات المستقبلية.

دعنا نكتب دالة لأخذ ملف الصورة كحجة وإرجاع الصورة الرمادية غير المعدلة الحجم. سنضع الدالة في أعلى السكريبت، بعد عمليات الاستيراد مباشرة:

import cv2
import glob
 
# Color to Gray Function
def color2gray(filename):
   
   img = cv2.imread(filename)  # Read the image
   gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Convert the image to grayscale
   gray_img_small = cv2.resize(gray_img, (960, 540)) # Resize the image for visualization purposes
   cv2.imshow('Grayscale Image', gray_img_small) # Display the gray image in a window called 'Grayscale Image'
   cv2.waitKey(0) # Press any key to close the window
 
   return gray_img
 
# Load the images in ascending order
image_files = sorted(glob.glob("./data/formula_one/*.jpg"))
 
# Loop through the files and display the images as grayscale
for i in image_files:
  color2gray(i)
 cv2.destroyAllWindows() # Close all the open windows

اكتب حزمة بايثون الخاصة بك

نصيحتي التالية هي متابعة للنصيحة السابقة. الآن بعد أن بدأت بالفعل في جعل الكود قابلاً لإعادة الاستخدام عن طريق إضافة دوال، يمكنك تخزين تلك الدوال في ملف بايثون. يمكنك استيراد هذا الملف مثل أي مكتبة وسحب دوالك متى احتجت إليها.

الخطوة التالية هي تنظيم الكود الخاص بك في فئات. يمكن أن يسمح لك هذا أيضًا باستخدام تابع dir() للوصول إلى قائمة الدوال في ملفك.

لنضع الدالة السابقة في ملف بايثون جديد يسمى utils.py ونستورده مثل أي حزمة بايثون. تذكر أن ملف utils.py يجب أن يكون في نفس الدليل.

import cv2
 
# Color to Gray Function
def color2gray(filename):
   
   img = cv2.imread(filename)  # Read the image
   gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Convert the image to grayscale
   gray_img_small = cv2.resize(gray_img, (960, 540)) # Resize the image for visualization purposes
   cv2.imshow('Grayscale Image', gray_img_small) # Display the gray image in a window called 'Grayscale Image'
   cv2.waitKey(0) # Press any key to close the window
 
   return gray_img

وملف gray.py المحدث:

import cv2
import glob
import utils
 
# Load the images in ascending order
image_files = sorted(glob.glob("./data/formula_one/*.jpg"))
# Loop through the files display them as grayscale
for i in image_files:
  utils.color2gray(i)
 cv2.destroyAllWindows() # Close all the open windows

إذا كان ملف utils.py موجودًا في دليل آخر، لأي سبب من الأسباب، فيمكنك استيراده إلى ملف gray.py:

import cv2
import glob
import sys
sys.path.append("your-path-to-utils")
import utils
 
# Load the images in ascending order
image_files = sorted(glob.glob("./data/formula_one/*.jpg"))
# Loop through the files display them as grayscale
for i in image_files:
  utils.color2gray(i)
  
cv2.destroyAllWindows() # Close all the open windows

هناك المزيد الذي يجب معرفته عن حزم بايثون، ولكن هذا من شأنه أن يساعدك في البدء. تعد سهولة القراءة إحدى مزايا تخزين دوالك في ملف بايثون مخصص، ولكنها تجعل أيضًا صيانة الكود أسهل.

يمكنك الوصول إلى قائمة الوظائف الخاصة بك باستخدام dir().

import utils
 
print(dir(utils))

نحصل على الناتج التالي:

['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'color2gray', 'cv2']

يمكنك رؤية color2gray، وهي الدالة التي عرّفناها من قبل. ولكن هذا ليس كل شيء. بعد ذلك، دعنا ننتقل إلى إحدى أفضل النصائح والحيل الخاصة بي في بايثون بينما ننظر إلى وحدة argparse.

تضمين وسيطات سطر الأوامر

هل تريد جعل السكريبت الخاص بك قابلاً لإعادة الاستخدام؟ قم بتعميمه! يا لها من مشكلة أن تضطر إلى البحث في السكريبت السابق الخاص بك لتعديله لحالة الاستخدام الحالية الخاصة بك! لذا، وفر على نفسك المتاعب واستخدم argparse. سوف تشكر نفسك لاحقًا!

Argparse هي مكتبة بايثون قوية. أشجعك على قراءة دليلي حول وحدة argparse لمعرفة المزيد عنها. وفي الوقت نفسه، دعنا نقوم بتحديث الكود الخاص بنا لتضمينها والقدرة على تنفيذ السكريبت بايثون الخاص بنا باستخدام وسيطات سطر الأوامر.

import cv2
import glob
import utils
import argparse as ap
 
# Define an argument parser object
parser = ap.ArgumentParser()
 
# Define the arguments to add
parser.add_argument("-d", "--directory", type=str, required=True, help="Directory of files to load")
parser.add_argument("-e", "--ext", type=str, default=".jpg", help="Define file extension")
args = parser.parse_args()
 
# Load the images in ascending order
image_files = sorted(glob.glob(args.directory+"*"+args.ext))
# Loop through the files display them as grayscale
for i in image_files:
   utils.color2gray(i)
 
cv2.destroyAllWindows() # Close all the open windows

يمكننا تشغيل السكريبت على النحو التالي:

python gray.py --directory ./data/formula_one/ --ext .jpg

يؤدي تضمين argparse في السكريبت إلى إعادة استخدامه بالكامل. باستخدامه، يمكنك كتابة الوسائط التي تحتاجها لتنفيذ البرامج النصية وفقًا لاحتياجاتك دون تحرير الكود مباشرةً.

استخدم سلسلة توثيقية بدلاً من التعليقات ذات السطر الواحد

بعد ذلك، أوصي باستخدام سلسلة توثيقية docstring بدلاً من التعليقات ذات السطر الواحد (أي التعليقات التي تحتوي على #). هناك سببان لذلك. من ناحية، يمكنك كتابة تعليقات متعددة الأسطر بسهولة وبشكل صحيح؛ ومن ناحية أخرى، يمكن لمستخدم البرنامج الوصول إلى التعليقات عن طريق استدعاء دالة help().

دعنا نقوم بتحرير ملف utils.py الخاص بنا ليشمل سلسلة الوثائق:

import cv2
 
# Color to Gray Function
def color2gray(filename):
   """
   This function reads an image and converts it to grayscale.
   For visualization purposes, we resize the output as a 960x540 image.
 
   Press any key to close the window and continue.
   """
   
   img = cv2.imread(filename)
   gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
   gray_img_small = cv2.resize(gray_img, (960, 540))
   cv2.imshow('Grayscale Image', gray_img_small)
   cv2.waitKey(0)
   return gray_img
print(help(color2gray))

ومن ثم، يمكننا تشغيل utils.py في الطرفية…

python utils.py

… واحصل على وثائق الدالة أدناه:

Help on function color2gray in module __main__:
 
color2gray(filename)
    This function reads an image and converts it to grayscale.
    For visualization purposes, we resize the output as a 960x540 image.
     
    Once the image is displayed, press any key to close the window and continue.
(END)

استخدم التحكم في الإصدار

هل تعطل جهاز الكمبيوتر المحمول الخاص بك لأن شخصًا ما سكب كوبًا من الماء عليه؟ أو هل فقدت جميع ملفاتك لأنك ارتكبت خطأ مطبعيًا عند تشغيل أمر Linux rm -rf لحذف دليل؟ لقد حدث لي كلا الأمرين، لذا لا داعي لتكرار خطأي!

لتجنب إعادة كتابة البرامج النصية أو استخدام مفك البراغي لفتح الكمبيوتر المحمول واستخراج القرص الصلب، وفر على نفسك بعض المتاعب مع التحكم في الإصدار. هناك بعض الخيارات المتاحة، مثل GitLab وGitHub وBeanstalk والمزيد. أنا شخصيًا أستخدم GitHub. سيضمن لك دفع الكود الخاص بك بانتظام أن يكون لديك دائمًا إصدار مشروع متاح. يمكن القيام بذلك في لمح البصر:

  • انتقل إلى دليل المشروع الخاص بك وافتح سطر الأوامر.
  • اكتب $ git init
  • اكتب $ git add your-project-filenames
  • اكتب $git commit
  • انتقل إلى حساب GitHub الخاص بك وقم بإنشاء مستودع جديد.
  • في سطر الأوامر، اكتب $ git remote add origin git@github.com:your-username/your-repo
  • اكتب $ git push

هذا كل شيء! أنت جاهز تمامًا. إذا كنت تريد معرفة المزيد حول كيفية البدء في استخدام GitHub، فهذا هو الوقت المناسب للتعلم!

تسلسل متغيرات بايثون لإعادة الاستخدام

يمكن أن يكون تسلسل الكائنات مفيدًا أيضًا. لنفترض أن إحدى الدوال تستغرق وقتًا طويلاً للتشغيل وسيتعين عليك إعادة استخدام نفس الناتج في ملفات متعددة، إما لأغراض البحث (مثل إجراء تجارب متعددة) أو لحالة استخدام أخرى. بدلاً من تشغيل الكود عدة مرات، يمكنك تسلسل الناتج عن طريق حفظه كملف pickle وإعادة تحميله في السكريبت التالي.

في مثالنا السابق، أعادت دالتنا الصورة ذات التدرج الرمادي كمصفوفة NumPy؛ يقوم السكريبت بتشغيل 50 صورة. ربما لديك سكريبت يقوم بنفس الأشياء لآلاف الصور وتحتاج إلى مصفوفات NumPy هذه لغرض آخر. يمكننا حفظ هياكل البيانات هذه لإعادة استخدامها في المستقبل لتجنب إعادة تشغيل الكود. دعنا نستورد pickle ونقوم بتحديث السكريبت الخاص بنا:

import cv2
import glob
import utils
import argparse as ap
import pickle as pkl
 
# Define an argument parser object
parser = ap.ArgumentParser()
 
# Define the arguments to add
parser.add_argument("-d", "--directory", type=str, required=True, help="Directory of files to load")
parser.add_argument("-e", "--ext", type=str, default=".jpg", help="Define file extension")
 
args = parser.parse_args()
 
# Load the images in ascending order
image_files = sorted(glob.glob(args.directory+"*"+args.ext))
# Create an empty list
gray_arr = []
# Loop through the files display them as grayscale
for i in image_files:
   arr = utils.color2gray(i)
   gray_arr.append(arr) # Append the gray arrays to a list
 
cv2.destroyAllWindows() # Close all the open windows
 
# Save the gray images as a list of Numpy arrays in a pickle file.
with open("gray_arr.pkl", "wb") as f:
   pkl.dump(gray_arr, f)

الآن، يمكنك تحميل ملف gray_arr.pkl مباشرةً واسترداد بنية البيانات المحفوظة. يمكن أن يوفر لك هذا الوقت من خلال تجنب إعادة تشغيل السكريبت عدة مرات لاسترداد النتائج. يمكن أن يكون أيضًا وسيلة لتحرير الذاكرة. بدلاً من تخزين القيم في قائمة، يمكنك حفظها كملف pickle وحذف المتغير لتقليل الحمل على ذاكرتك.

استخدم مكتبات بايثون المحسنة

نصيحتي الأساسية التالية تأتي مباشرة من المثال السابق حيث قمنا بحفظ مجموعة من الصور كمصفوفات NumPy – وهي مكتبة بايثون مكتوبة بلغة C. C هي لغة أسرع بكثير من بايثون. و على الرغم من كونها أبطأ، فهي سهلة الاستخدام وتميل إلى جعل التطوير أسرع، وهو ما يفسر شعبيتها وتعدد استخداماتها.

من خلال استخدام المكتبات المكتوبة بلغة C، يمكنك جعل كود بايثون أسهل وأسرع كثيرًا. إذا كان جهازك يدعم Cuda، فيمكنك أيضًا استخدام CuPy، وهو إصدار من NumPy مُحسَّن لوحدات معالجة الرسومات، مما يجعل كودك أسرع. هذه المكتبات أيضًا مريحة للغاية وتسمح لك بإجراء عمليات حسابية معقدة باستدعاء دالة واحدة.

كتابة كود بايثون

نصيحتي التالية هي استخدام جمل قصيرة في بايثون لجعل الكود أكثر إيجازًا وأناقة. يخزن الكود السابق ناتج دالة color2gray في قائمة تقليدية:

# Create an empty list
gray_arr = []
# Loop through the files display them as grayscale
for i in image_files:
   arr = utils.color2gray(i)
   gray_arr.append(arr)

ومع ذلك، يمكننا إعادة كتابة هذا بأسلوب Pythonic على شكل سطر واحد:

gray_arr = [utils.color2gray(i) for i in image_files]

الآن أصبح الكود الخاص بنا أكثر إيجازًا وأناقة – والأهم من ذلك، أكثر توافقًا مع لغة بايثون!

احذر من الأخطاء المحتملة

عندما يعمل السكريبت بشكل صحيح دون إلقاء أي أخطاء، فهذا أمر رائع. ولكن نادرًا ما يحدث هذا. وفي بعض الأحيان تكون الأخطاء جزءًا من العملية ولا ينبغي لها أن توقف السكريبت. على سبيل المثال، قد ترغب في استخراج بعض الصور، ولكن الطلب يلقي خطأ استثناء ولا يمكنه إرجاع أي صورة. ثم يتوقف السكريبت دون تنفيذ التعليمات التي طلبت منه القيام بها. وبالتالي، فإن الطريقة التي تنهي بها السكريبت في بايثون مهمة. لمنع السكريبت من التوقف، يمكنك الاستفادة من try-except؛ في هذه الحالة، ستتخطى معالجة الاستثناءات الملف فقط وتمنع السكريبت من التوقف.


اكتشاف المزيد من بايثون العربي

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

Scroll to Top

اكتشاف المزيد من بايثون العربي

اشترك الآن للاستمرار في القراءة والحصول على حق الوصول إلى الأرشيف الكامل.

Continue reading