PythonGuide/Modules Packages

من PFWiki

اذهب إلى: تصفح, البحث

محتويات

الحزم والوحدات

مقدمة

بايثون مشهورة بعبارة batteries included فاللغة نفسها لاتقدم سوى الsyntax ولكن لإستخدامها تم تقسيم الخدمات الى ملفات خارجية بإسم modules واذا كانت modules مترابطة تم تحزيمها فى package على سبيل المثال بايثون لاتقوم بتوفير الدوال الخاصة بالرياضيات مباشرة

>>> cos(30)
 
Traceback (most recent call last):
 
  File "<stdin>", line 1, in <module>
 
NameError: name 'cos' is not defined


معنى السابق وجود خطأ فى السطر الأول من ال module “ابسط وحدة لتطبيق بايثون" ونوع الخطأ هو عدم وجود دالة ال cos فى مساحة البرنامج اذا ؟ كيف اتعامل مع الدوال الرياضية ؟ يوجد فى مكتبات بايثون الأساسية modules لعمل معظم انواع التطبيقات قواعد بيانات شبكات حسابات معالجة بيانات .. الخ الخ


استيراد وحدة

قم بإستدعاء الmodule المسماة math وهى وحدة تشمل العديد والعديد للقيام بالعمليات الحسابية بإستخدام import

import math

هكذا قمنا بإستدعاء الوحدة لساحة البرنامج لاحظ قد لاتكون ال module موجود فينتج ImportError

>>> try:
 
...     import mymath
 
... except ImportError, e:
 
...     print e
 
... 
No module named mymath


تقدر تستخدم ال magical import لإستدعاء الموديلز ايضا

>>> msys=__import__('sys')

تقدر تستخدم as لعمل تسميه مختلفة( لموديل او احد عناصر موديل الخ) هنا للموديل مثل المثال السابق msys كبديل ل sys

>>> import sys as mysys

البحث عن نيمو (اين توجد هذه الوحدات)؟

اين توجد هذه الوحدات؟ هل يوجد شروط لإستدعاءها ام ماذا ؟ المفسر لايعلم عن كل ملف بايثون على جهازك ولكن هناك بعض الأماكن اللتى يبحث فيها قبل ان يرسل لك ال ImportError مثل المجلد الحالى او مجلد بايثون الإفتراضى او مجلد site-packages (يفضل استخدامه عند اضافة اى وحدات خارجية لبايثون) للحصول على القائمة كاملة التى يبحث فيها المفسر استدعى sys.path

>>> import sys
>>> sys.path
['', '/usr/lib/python2.5/site-packages/Tempita-0.2-py2.5.egg', '/usr/lib/python2.5/site-packages/Mako-0.2.2-py2.5.egg', 
....
....
>>>

الوحدة الأولى

يفضل دائما عند انشاء موديل او اى سكربت انك تنشئ هيدر مشابه للتالى

##################################################
 
# Author: Ahmed Youssef
 
# License: GPL V3
 
# Module: firstmodule
 
# Purpose: Learning modules
 
# Date: 12-20-2008
 
###################################################


انشئ ملف firstmodule.py وعرف فيها مجموعة من الدوال كالتالى

def aloha():
 
	print "Aloha!"
 
 
 
def adios():
 
	print "Adios!"


ايه الهدف من ال modules قلنا ؟ فصل التطبيق لأكثر من جزء لإمكانية استخدام خدماته اكثر من مرة وايضا تسهيل تقسيم العمل مثال شخص يكون مسئول عن جزئية التعامل مع قاعدة البيانات وشخص اخر مسئول عن الواجهة وهكذا

اوكى كتبنا الموديل ماذا الآن ؟ انشئ ملف جديد وليكن greeter.py هيتم فيه استخدام الدوال aloha, adios الموجودة فى firstmodule.py

import firstmodule
 
firstmodule.aloha()
 
firstmodule.adios()


عند التنفيذ [quote]striky@striky-desktop:~/workspace/pytut/src$ python greeter.py

Aloha!

Adios![/quote]

[b] Using from[/b]

ربما لاتريد ان تكتب اسم الموديل فى كل مرة او ربما ماتريده او دالة معينة فقط الخ

from firstmodule import aloha, adios
aloha()
 
adios()


او ربما تريد استدعاء جميع محتويات module ما قم فقط بتنفيذ جملة الإستدعاء

from somemodule import *

حيث * تعنى جميع المحتويات [b] Reloading [/b] ربما تستخدم بيئة تفاعلية او ربما نظام معين يكون عملية اعادة التشغيل فيه مكلفة او غيرهاا وقمت بتعديل module معينة قم بتنفيذ الدالة reload لإعادة تحميل ال module بالتعديلات الجديدة

[b]__main__ [/b] احترس من اختبار الكود فى ال module وإلا سيتم تنفيذه بمجرد استدعائها اذا عدلت كود ال firstmodule.py الى

def aloha():
 
	print "Aloha!"
 
def adios():
 
	print "Adios!"
 
aloha()

وقمت بتنفيذ ال greeter.py ستجد الناتج كالتالى [quote]striky@striky-desktop:~/workspace/pytut/src$ python greeter.py Aloha! Aloha! Adios![/quote]


مع اننا استدعينا aloha مرة واحدة ولكن تم تنفيذها مرتان وذلك بسبب استدعائها فى ال firstmodule والحل ؟ الااستطيع اختبار الكود ؟

اليس الأفضل ان تختبر اولا اذا كانت ال module هى اللتى يتم تنفيذها كملف رئيسى او مجرد مستدعاه فى ملف اخر ؟ كيف اعلم هذا ؟ بكل بساطة توفر لك ال modules متغير خاص بإسم __name__ يحوى اسم ال module الحالية وهو "__main__”

قم بإضافة شرط فى نهاية ال firstmodule كالتالى

if __name__=="__main__":
 
	#Testing...
	aloha()


وتم حل المشكلة عند تنفيذلك لل greeter.py سيتم طباعة Aloha! و Adios! وعند تنفيذك لل firstmodule فتكون هى السكربت الرئيسى اللذى سيتم تنفيذه او ال __main__ فيتم تنفيذ كود الإختبار او اىاكان :)

[b]__all__[/b]

للتحكم فيما يمكن استدعاءه من وحدة ما تستطيع استخدام متغير خاص بإسم __all__ __all__=["aloha"]

الحزم

للآن جيد ماذا لو زاد عدد ال modules تستطيع بالتأكيد انشاء المئات من تلك الملفات ولكن يجب عليك تحزيم الmodules المترابطة مثلا اذا كنا ننشئ مشروع عن التعامل مع قواعد بيانات مختلفة oracle, sqlite, mysql وغيرهم اليس الأفضل تجميعهم فى حزمة ما بإسم databases مثلا ؟ ويتم استدعاءها

import databases.mysql

او مثلا

from databases import mysql

بكل تأكيد هذا اكثر تنظيما

myfirstpackage/
 
	|-- __init__.py
 
	|-- mysql.py
 
	|-- oracle.py
 
	`-- sqlite.py


لدينا حزمة بإسم myfirstpackage وتشمل 4 ملفات 1- ال __init__ وفيه بيتم تحديد الوحدات اللتى نريد تحميلها مباشرة وربما بعض المتغيرات الأساسية ؟ 2- 3 وحدات بإسم mysql.py, oracle.py, sqlite.py معرفين كالتالين

الملف mysql.py

def about():
 
	print "mysql module."

الملف oracle.py

def about():
 
	print "oracle module."


الملف sqlite.py

def about():
 
	print "sqlite module."

الملف __init__

print "__init__ myfirstpackage"
 
import mysql
VERSION="1.42.0"


لاحظ اننا قمنا بعمل import ل mysql مباشرة وحددنا متغير بإسم VERSION

انشئ ملف dbtester.py

import myfirstpackage
 
 
print dir(myfirstpackage)
 
print myfirstpackage.VERSION
 
myfirstpackage.mysql.about()
 
myfirstpackage.sqlite.about()

ستجد الناتج مشابه للتالى

striky@striky-desktop:~/workspace/pytut/src$ python dbtester.py
 
__init__ myfirstpackage
 
['VERSION', '__builtins__', '__doc__', '__file__', '__name__', '__path__', 'mysql']
 
1.42.0
 
mysql module.
 
Traceback (most recent call last):
 
  File "dbtester.py", line 6, in <module>
 
    myfirstpackage.sqlite.about()
 
AttributeError: 'module' object has no attribute 'sqlite'


وبكل تأكيد لن سيتم رفع استثناء AttributeError بسبب عدم استدعاء sqlite للساحة إلا اذا قمت بإضافتها يدويا import myfirstpackage.sqlite


[b] Platform[/b]

كثيرا مانحتاج للحصول على معلومات عن النظام الذي يعمل عليه البرنامج (لإختبار التوافقية ، الإعتماديات او ربما العلم بالشئ) تقدم لنا بايثون وحدة بإسم platform

مثال

striky@striky-desktop:~/workspace/pytut/src$ python platformreport.py 
 
[architecture => ('32bit', 'ELF')]
 
[dist => ('debian', 'lenny/sid', '')]
 
[java_ver => ('', '', ('', '', ''), ('', '', ''))]
 
[libc_ver => ('glibc', '2.4')]
 
[mac_ver => ('', ('', '', ''), '')]
 
[machine => i686]
 
[node => striky-desktop]
 
[platform => Linux-2.6.27-9-generic-i686-with-debian-lenny-sid]
 
[processor => ]
 
[python_build => ('r252:60911', 'Oct  5 2008 19:24:49')]
 
[python_compiler => GCC 4.3.2]
 
[python_version => 2.5.2]
 
[python_version_tuple => ['2', '5', '2']]
 
[release => 2.6.27-9-generic]
 
[system => Linux]
 
[uname => ('Linux', 'striky-desktop', '2.6.27-9-generic', '#1 SMP Thu Nov 20 21:57:00 UTC 2008', 'i686', '')]
 
[version => #1 SMP Thu Nov 20 21:57:00 UTC 2008]
 
[win32_ver => ('', '', '', '')]

تستطيع بكل تأكيد كتابة كل function مثلا platform.dist() platform.machine() platform.uname() الخ الخ ولكن ربما نستخدم حيلة صغيرصة لإستدعاءهم جميعا ؟

import platform
 
for s in dir(platform):
 
	if not s.startswith("_"): #If it does not start with an underscore.
 
		f=getattr(platform, s)   #Fetch the attribute (should be a function..)
 
		try:
 
			print "[%s => %s]"%(s, f()) #Prints attr, returned value
 
		except:
 
			pass #Global catch for functions requires params(e.g popen).

هنا نقوم بعرض محتويات platform بإستخدام dir ونحصل على ال function object بإستخدام getattr من الوحدة وبإسم الدالة ونقوم بتنفيذها (مجرد استدعائها بعد الحصول عليها) وبس كدا


→ Exceptions Errors Modules Packages External Programs ←
أدوات شخصية