آموزش برنامه نویسی پایتون

به روز ترین مطالب آموزشی و متدلوژی های برنامه نویسی

آموزش افزونه نویسی برای پایتون با زبان C

۳۳ بازديد
امروز با مقاله دیگری از سری مقاله های آموزش پایتون همراه شما هستیم، در این مقاله میخواهیم چگونگی افزونه نویسی در پایتون به کمک کدهای زبان C را مورد بررسی قرار دهیم..
به منظور نوشتن افزونه های اختصاصی جهت استفاده در اسکریپت های پایتون و اپلیکیشن های خود، لازم است به فایل های header پایتون دسترسی داشته باشید.در دستگاه هایی که سیستم عامل Unix بر روی آن نصب است، می بایست یک پکیج مختص توسعه دهنده (developer-specific) نظیر python2.5-dev را نصب نمایید.
کاربران ویندوز این فایل های header را به هنگام استفاده از binary Python installer به صورت یک پکیج دریافت می کنند. علاوه بر آن، برای درک مفاهیم این مبحث و نوشتن افزونه های اختصاصی خود جهت استفاده در اسکریپت های پایتون، لازم است آشنایی در سطح پیشرفته با زبان های C یا ++C داشته باشید.
 
آموزش Python : اولین نمونه از افزونه اختصاصی Python
کد ماژول و افزونه های پایتون، بایستی مانند زیر در چهار بخش سازمان دهی شود:
  • فایل header با اسم و پسوند Python.h.
  • توابع C که می خواهید به عنوان interface و الگوی پیاده سازی ماژول اختصاصی خود در اختیار توسعه دهنده قرار دهید.
  • یک جدول که اسم توابع اختصاصی شما را به توابع C داخل افزونه (کتابخانه یا ماژول) نگاشت می کند (method mapping table).
  • یک تابع سازنده جهت مقداردهی اولیه و نمونه سازی از کلاس (initialization function).
 
فایل Python.h
لازم است فایل Python.h را داخل فایلی که کدهای C شما را دربرمی گیرد (source file) قید نمایید. بدین وسیله شما به توابع کتابخانه ای درون ساخته ی پایتون (internal Python API) که برای ادغام و معرفی ماژول مورد نظر در interpreter (hook کردن کد ماژول شما در مفسر) بکار می رود، دسترسی خواهید داشت. لازم است Python.h را قبل از هر فایل header مورد نیاز دیگری لحاظ نمایید.
 
توابع C
اسم متد، نوع و تعداد پارامترهای ورودی (Signature) توابع اختصاصی شما و پیاده سازی آن، بایستی بر اساس یکی از الگوهای زیر انجام شود:
static PyObject *MyFunction( PyObject *self, PyObject *args );
static PyObject *MyFunctionWithKeywords(PyObject *self,
                                 PyObject *args,
                                 PyObject *kw);
static PyObject *MyFunctionWithNoArgs( PyObject *self );

هر یک از متدهای اعلان شده ی فوق، در خروجی خود یک آبجکت Python برمی گرداند. در پایتون مفهومی به نام تابع void (تابعی که خروجی ندارد یا مقداری را برنمی گرداند) وجود ندارد. اگر شما نمی خواهید که توابع مقدار خروجی داشته باشند، لازم است مقدار None را بازگردانی نمایید. header های پایتون یک macro (خط دستور) به نام Py_RETURN_NONE در خود به صورت از پیش تعریف شده دارند که این کار را انجام می دهند.
از آنجایی که اسم توابع C هیچگاه خارج از ماژول/افزونه قابل مشاهده و دسترسی نیستند، شما می توانید هر اسمی برای متدهای اختصاصی خود انتخاب کنید. لازم به ذکر است که این توابع با کلیدواژه ی static تعریف می شوند. اسم توابع C معمولا از ترکیبی از اسم ماژول و متد مورد نظر تشکیل می شود. در زیر نمونه ای را مشاهده می کنید:
static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Do your stuff here. */
   Py_RETURN_NONE;
}

کد حاضر یک تابع Python به نام func را تعریف می کند که داخل افزونه ی module کپسوله سازی شده است. حال شما به این توابع C داخل جدول نگاشت متد (method table) Pointer و اشاره گر تعریف می کنید که در بخش بعدی کد برنامه ی شما انجام می شود.
 
آموزش برنامه نویسی پایتون : جدول نگاشت توابع
این جدول نگاشت متد (method table) یک آرایه ی ساده از structure های PyMethodDef است (PyMethodDef یک مدل برای تعریف متد است). این structure ساختاری مشابه زیر دارد:
struct PyMethodDef {
   char *ml_name;
   PyCFunction ml_meth;
   int ml_flags;
   char *ml_doc;
};

در زیر هر یک از اعضای این ساختار شرح داده اند:
  • فیلد ml_name : اسم تابع پایتون.
  • فیلد ml_meth : آدرس تابعی که هر یک از signature های نام برده در بخش قبلی را دارا می باشد.
  • فیلد ml_flags : این فیلد به مفسر پایتون اعلان می کند که فیلد دوم (ml_meth) کدام یک از signature های نام برده را اتخاذ می کند :
  1. این flag معمولا مقداری از METH_VARARGS دارد.
  2. اگر می خواهید آرگومان های کلیدواژه ای را در تابع تزریق نمایید، این flag می تواند OR بیتی با METH_KEYWORDS را شامل شود.
  3. این flag همچنین می تواند مقدار METH_NOARGS را داشته باشد، بدین معنی که هیچ پارامتری به تابع فرستاده نمی شود.
  • فیلد ml_doc : این docstring (رشته یا comment ای که توضیحی درباره ی کارایی تابع می دهد) تابع است. اگر برنامه نویس comment ای برای تابع تنظیم نکند، در آن صورت مقدار آن NULL خواهد بود.
این جدول بایستی با یک sentinel که از NULL و 0 برای اعضای مرتبط تشکیل شده، خاتمه یابد.
 
مثال :
برای متد اعلان شده در بالا، از جدول نگاشت تابع (method mapping table) زیر استفاده می کنیم:
static PyMethodDef module_methods[ ] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { NULL, NULL, 0, NULL }
};
 
آموزش زبان پایتون : تابع مقداردهی اولیه (initModule)
آخرین بخش ماژول یا افزونه ی اختصاصی شما بایستی تابع مقداردهنده ی اولیه (initialization function) را شامل شود. این تابع را مفسر پایتون زمانی که ماژول در حافظه بارگذاری می شود، فرامی خواند. لازم است اسم این تابع initModule انتخاب شود (Module اسم ماژول و init اسم خود تابع می باشد).
تابع مقداردهنده ی اولیه بایستی از کتابخانه که می نویسید export و خروجی گرفته شده باشد. header های Python با اعلان دستور PyMODINIT_FUNC امکان انجام این کار را در محیطی که اسکریپت ها در آن کامپایل می شوند را فراهم می آورد. کافی است به هنگام تعریف تابع مورد نظر از آن استفاده نمایید.
تابع مقداردهنده ی اولیه ی زبان C شما دارای ساختار کلی زیر می باشد:
PyMODINIT_FUNC initModule() {
   Py_InitModule3(func, module_methods, "docstring...");
}
در زیر شرح هر یک از پارامترهای تابع Py_InitModule3 را به تفصیل مشاهده می کنید:
  • پارامتر func : تابعی است که قرار است export و به اصطلاح خروجی گرفته شود.
  • پارامتر module_methods : اسم جدول نگاشت تابع (mapping table) که در بالا به آن اشاره شد.
  • پارامتر docstring : این پارامتر همان رشته ی متنی و comment ای است که جهت ارائه ی توضیح درباره ی قابلیت تابع در افزونه ی اختصاصی درج می شود.
در زیر تمامی بخش های تشکیل دهنده یک افزونه استاندارد را یکجا مشاهده می کنید:
#include < python.h>
static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Do your stuff here. */
   Py_RETURN_NONE;
}
static PyMethodDef module_methods[ ] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { NULL, NULL, 0, NULL }
};
PyMODINIT_FUNC initModule() {
   Py_InitModule3(func, module_methods, "docstring...");
}
< /python.h>
 
مثال :
نمونه کاربردی که کلیه مفاهیم فوق را به صورت عملی بکار می برد را در زیر مشاهده می کنید:
#include < python.h>
static PyObject* helloworld(PyObject* self)
{
    return Py_BuildValue("s", "Hello, Python extensions!!");
}
static char helloworld_docs[ ] =
    "helloworld( ): Any message you want to put here!!n"
static PyMethodDef helloworld_funcs[ ] = {
    {"helloworld", (PyCFunction)helloworld, 
     METH_NOARGS, helloworld_docs},
    {NULL}
};
void inithelloworld(void)
{
    Py_InitModule3("helloworld", helloworld_funcs,
                   "Extension module example!");
}
< /python.h>

دستور Py_BuildValue در مثال بالا، یک مقدار Python را build یا کامپایل می کند. کد مورد نظر را داخل فایل hello.c ذخیره نمایید. در زیر با نحوه ی کامپایل و نصب ماژول که از اسکریپت پایتون فراخوانی می شود، را خواهید آموخت.
 
کامپایل و نصب افزونه ها (build)
پکیج distutils توزیع و نصب ماژول های پایتون، خواه ماژول های اصلی و خالص خود پایوتن باشد خواه ماژول های اختصاصی و تنظیم شده توسط توسعه دهنده، را با روشی استاندارد بسیار آسان می سازد. ماژول ها در همان قالب اولیه (source form) توزیع شده و در اختیار برنامه نویس قرار می گیرد. برنامه نویس سپس ماژول مورد نظر را با فراخوانی اسکریپت نصب (setup script) به نام setup.py ، نصب می نماید.
جهت نصب ماژول ذکر شده در بالا، بایستی اسکریپت setup.py را آماده نموده و به روش زیر اجرا نمایید:
from distutils.core import setup, Extension
setup(name='helloworld', version='1.0',  
      ext_modules=[Extension('helloworld', ['hello.c'])])

اکنون با فراخوانی دستور زیر، تمامی مراحل لازم نظیر کامپایل و آماده سازی (linking & compilation) کد را انجام دهید. کد زیر کلیه ی مراحل مورد نیاز کامپایل و لینک ماژول با کامپایلر، دستورات linker و flag های مناسب را انجام داده، متعاقبا خروجی (.dll) را در پوشه ی مربوطه جایگذاری (کپی) می کند.
$ python setup.py install

در سیستم های مبتنی بر Unix، لازم است این دستور را با حساب کاربری root اجرا نمایید تا امکان یا مجوز درج داده در پوشه ی site-packages را داشته باشید. در سیستم عامل ویندوز لازم به انجام این کار نیست.
 
آموزش Python : وارد کردن و استفاده از افزونه ها در پروژه
پس از نصب افزونه ی دلخواه خود، می توانید آن را در اسکرپیت پایتون خود با دستور import وارد کرده و فراخوانی نمایید:
#!/usr/bin/python
import helloworld
print helloworld.helloworld()
خروجی زیر را تولید می کند:
Hello, Python extensions!!
 
ارسال پارامتر به تابع
در طول توسعه پروژه، گاه می بایست توابعی را اعلان و فراخوانی نمایید که پارامترهایی را به عنوان ورودی می پذیرد. از اینرو بایستی signature (اسم تابع + نوع، تعداد پارامتر ورودی) مربوطه را برای توابع C ماژول اختصاصی خود انتخاب نمایید. به طور مثال، تابع ذیل را در نظر بگیرید که تعدادی پارامتر به عنوان ورودی پذیرفته و بدین صورت اعلان می شود:
static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Parse args and do something interesting here. */
   Py_RETURN_NONE;
}

متد table که تابع جدید را در خود کپسوله می کند، به صورت زیر خواهد بود:
static PyMethodDef module_methods[ ] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { "func", module_func, METH_VARARGS, NULL },
   { NULL, NULL, 0, NULL }
};

می توانید با استفاده از تابع کتابخانه ای PyArg_ParseTuple آرگومان های مورد نیاز را از متغیر اشاره گر (pointer) به PyObject که به عنوان آرگومان به تابع C ارسال شده، استخراج نمایید.
اولین آرگومان ارسالی به PyArg_ParseTuple، آرگومان args می باشد. این آرگومان همان آبجکتی است که باید parse یا تحلیل نحوی شود. پارامتر دوم یک رشته ی فرمت دهی (format string) است که آرگومان ها را به آن شکلی که مورد انتظار شما است، به نمایش می گذارد. به تعداد آرگومان ها، یک یا چند کاراکتر در رشته ی فرمت دهی وجود دارد که نشانگر آرگومان های مزبور می باشند.
static PyObject *module_func(PyObject *self, PyObject *args) {
   int i;
   double d;
   char *s;
   if (!PyArg_ParseTuple(args, "ids", &i, &d, &s)) {
      return NULL;
   }
   /* Do something interesting here. */
   Py_RETURN_NONE;
}

با کامپایل نمودن ورژن جدید از ماژول خود و وارد کردن آن در متن پروژه، قادر خواهید بود تابع مورد نظر را با تعداد دلخواه و نوع مختلف از آرگومان ها فراخوانی نمایید:
module.func(1, s="three", d=2.0)
module.func(i=1, d=2.0, s="three")
module.func(s="three", d=2.0, i=1)
 
تابع PyArg_ParseTuple
در زیر تعداد و نوع ورودی های تابع را به شکل استاندارد (signature) PyArg_ParseTuple مشاهده می کنید:
int PyArg_ParseTuple(PyObject* tuple,char* format,...)

در صورتی که عملیات با موفقیت انجام شود، مقداری غیر صفر و چنانچه عملیات ناموفق بوده و خطا رخ داد، مقدار 0 در خروجی بازگردانی می شود. tuple، آبجکت PyObject* بوده که همان آرگومان دوم ارسال شده به تابع C می باشد. آرگومان سوم، format، یک رشته ی C می باشد که نشانگر آرگومان های الزامی و اختیاری می باشد.
در زیر لیستی از کدهای فرمت دهی که به تابع PyArg_ParseTuple ارسال می شود همراه با شرح هر یک مشاهده می کنید:
  • کد c در پایتون معادل char در زبان C : یک رشته پایتون با طول 1 (رشته ی حاوی یک کاراکتر) معادل char در C می شود.
  • کد d در پایتون معادل double در زبان C : یک مقدار عددی float (ممیز و اعشاری) که معادل double (اعشاری با دقت بیشتر) در C محسوب می شود.
  • کد f در پایتون معادل float در زبان C : یک float (مقدار عددی اعشاری از نوع float) در پایتون معادل float در C محسوب می شود.
  • کد i در پایتون معادل int در زبان C : یک int (نوع عدد صحیح) معادل long در زبان C درنظر گرفته می شود.
  • کد l در پایتون معادل long در زبان C : یک int در زبان پایتون معادل نوع داده ای long در زبان C در نظر گرفته می شود.
  • کد L در پایتون معادل long long در زبان C : یک int یا نوع داده ای عدد صحیح در زبان پایتون، معادل long long در زبان C محسوب می شود.
  • کد O در پایتون معادل PyObject* در زبان C : یک اشاره گر غیر NULL به آرگومان Python بازگردانی می کند.
  • کد s در پایتون معادل char* در زبان C : رشته پایتون بدون مقادیر null جاسازی شده (embedded) به char* در زبان C فرمت دهی / تبدیل می شود.
  • کد s# در پایتون معادل char*+int در زبان C : رشته Python را به آدرس و طول سازگار در C تبدیل می کند.
  • کد t# در پایتون معادل char*+int در زبان C : کاربردی مشابه s# دارد با این تفاوت که هر آبجکتی که اینترفیس read-only را پیاده سازی کند، می پذیرد.
  • کد u در پایتون معادل Py_UNICODE* در زبان C : کاراکترهای Unicode (null-terminated buffer) مستقر در بافر که انتهای آن به null ختم می شود را به آبجکت Unicode پایتون تبدیل می کند.
  • کد u# در پایتون معادل Py_UNICODE*+int در زبان C : نوع دیگر از u که در دو متغیر C ذخیره می شود، اولی یک اشاره گر به آدرس Unicode مستقر در بافر و دومی طول آن.
  • کد w# در پایتون معادل char*+int در زبان C : مشابه s#، اما هر آّبجکتی که اینترفیس read/write بافر را پیاده سازی می کند، پذیرفته و با آن سازگاری دارد.
  • کد z در پایتون معادل char* در زبان C : کاربری مشابه s دارد با این تفاوت که None نیز می پذیرد (char* زبان C را بر روی NULL تنظیم می کند).
  • کد z# در پایتون معادل char*+int در زبان C : کاربردی مشابه s# دارد اما None نیز می پذیرد (char* زبان C را روی NULL تنظیم می نماید).
  • کد (...) در پایتون معادل as per ... در زبان C : یک دنباله (sequence) پایتون که هر آیتم در آن یک آرگومان در نظر گرفته می شود.
  • کد | در پایتون معادل double در زبان C : آرگومان های زیر اختیاری می باشد.
  • کد : در پایتون معادل double در زبان C : قبل از اسم تابع در پیغام های خطا قرار می گیرد.
  • کد ; در پایتون معادل double در زبان C : قبل از درج کل متن پیغام خطا قرار می گیرد.
 
بازگردانی مقادیر در خروجی
تابع Py_BuildValue، درست مانند PyArg_ParseTuple ، یک رشته ی فرمت دهی (string format) به عنوان ورودی دریافت می کند. بجای ارسال آدرس مقادیری که کامپایل می کنید، بایستی خود مقادیر را به عنوان آرگومان به تابع مورد نظر بفرستید. در زیر مثالی از نحوه ی پیاده سازی یک تابع که عملیات جمع را انجام می دهد، تابع add، مشاهده می کنید:
static PyObject *foo_add(PyObject *self, PyObject *args) {
   int a;
   int b;
   if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
      return NULL;
   }
   return Py_BuildValue("i", a + b);
}

معادل پیاده سازی آن در زبان پایتون به صورت زیر می باشد:
def add(a, b):
   return (a + b)
می توانید دو خروجی از این تابع بازگردانی نمایید. این عملیات در پایتون با یک لیست قابل پیاده سازی خواهد بود:
static PyObject *foo_add_subtract(PyObject *self, PyObject *args) {
   int a;
   int b;
   if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
      return NULL;
   }
   return Py_BuildValue("ii", a + b, a - b);
}

معادل پیاده سازی آن در زبان پایتون به صورت خواهد بود:
def add_subtract(a, b):
   return (a + b, a - b)

 
تابع Py_BuildValue
در زیر روش استاندارد تنظیم اسم تابع، نوع و تعداد پارامترهای ورودی آن که signature خوانده می شود را ویژه ی تابع Py_BuildValue مشاهده می کنید:
PyObject* Py_BuildValue(char* format,...)
پارامتر format، یک رشته ی C بوده و نشانگر آبجکت Python است که پارامتر حاضر باید نهایتا به آن کامپایل شود. آرگومان های زیر مقادیر C هستند که خروجی از آن ها ساخته و کامپایل می شود. نتیجه ی PyObject* یک اشاره گر (reference) جدید می باشد.
جدول زیر code string های پرکاربرد را با ذکر کارایی هر یک در اختیار شما قرار می دهد:
  • کد c در پایتون معادل char در زبان C : یک char زبان C، به رشته ای با طول یک کاراکتر تبدیل می شود.
  • کد d در پایتون معادل double در زبان C : یک نوع عددی double زبان C، به float در پایتون تبدیل می شود.
  • کد f در پایتون معادل float در زبان C : یک float یا نوع عددی اعشاری زبان C، به همان float در پایتون تبدیل می شود.
  • کد i در پایتون معادل int در زبان C : یک Int زبان C به همان int (نوع عددی صحیح) در پایتون تبدیل می شود.
  • کد l در پایتون معادل long در زبان C : یک long در زبان C به int در پایتون تبدیل می شود.
  • کد N در پایتون معادل PyObject* در زبان C : یک آبجکت پایتون ارسال کرده ولی reference count (تعداد دفعاتی که آبجکت مورد نظر به آن دسترسی صورت می گیرد) آن را افزایش نمی دهد.
  • کد O در پایتون معادل PyObject* در زبان C : یک آبجکت پایتون ارسال کرده و reference count آن را طبق انتظار یک واحد افزایش می دهد.
  • کد O& در پایتون معادل convert+void* در زبان C : رشته پایتون بدون مقادیر null جاسازی شده (embedded) به char* در زبان C فرمت دهی / تبدیل می شود.
  • کد s در پایتون معادل char* در زبان C : یک char* که در انتهای خود 0 داشته را به رشته ی Python تبدیل می نماید یا NULL را به None.
  • کد s# در پایتون معادل char*+int در زبان C : یک رشته ی C و طول (length) آن را به یک آبجکت Python تبدیل می کند. اگر اشاره گر از نوع string (string pointer) برابر NULL باشد، طول یا length نادیده گرفته شده و None در خروجی بازگردانی می کند.
  • کد u در پایتون معادل Py_UNICODE* در زبان C : یک رشته که در سطح زبان C تعریف شده و انتهای آن مقدار NULL وجود دارد را به یونیکد پایتون تبدیل کرده و اگر NULL بود آن را به None تبدیل می کند. Buffer ای از داده های Unicode که انتهای آن null وجود دارد را به آبجکت پایتون تبدیل می کند. اگر Unicode buffer برابر NULL بود، در خروجی None بازیابی می شود.
  • کد u# در پایتون معادل Py_UNICODE*+int در زبان C : یک رشته ی تعریف شده در سطح C و طول آن را به آبجکت Unicode پایتون تبدیل می کند یا NULL را به None تبدیل می کند. به عبارت دیگر، یک Unicode (که استانداردهای USC-2 یا UCS-4) مستقر در buffer یا حافظه میانی و طول (length) آن را به آبجکت Unicode پایتون تبدیل می کند. اگر اشاره گر به Unicode موجود در buffer برابر NULL بود، طول آن نادیده گرفته شده و None را در خروجی برمی گرداند.
  • کد w# در پایتون معادل char*+int در زبان C : مشابه s#، با این تفاوت که هر آبجکتی که اینترفیس read-write را پیاده سازی می کند، می پذیرد. متغیر char * طوری تنظیم شده که به اولین بایت از buffer اشاره کند و Py_ssize_t را بر روی طول buffer تنظیم می کند.
  • کد z در پایتون معادل char* در زبان C : مشابه s، با این تفاوت که None نیز می پذیرد (char* در C را روی NULL تنظیم می کند).
  • کد z# در پایتون معادل char*+int در زبان C : کاربردی مشابه s# دارد (char* در C را بر روی NULL تنظیم می کند).
  • کد (...) در پایتون معادل as per ... در زبان C : از دنباله ای از مقادیر C، یک متغیر tuple در پایتون می سازد.
  • کد [...] در پایتون معادل as per ... در زبان C : از مقادیر C، یک لیست (list) در پایتون تولید می کند.
  • کد {...} در پایتون معادل as per ... در زبان C : از دنباله ای از مقادیر C، یک dictionary که المان های آن به صورت متناوب، کلید و مقدار، سازمان دهی شده، ایجاد می کند.
به طور مثال تابع Py_BuildValue("{issi}",23,"zig","zag",42) یک dictionary پایتون به صورت {23:'zig','zag':42} در خروجی تولید می کند.

با دیگر آموزش های ما در زمینه آموزش پایتون و دیگر زبان های برنامه نویسی همراه ما باشید...

آموزش کار با XML در پایتون

۳۶ بازديد
در این مقاله از مجموعه مقاله های آموزش پایتون به بررسی کار با XML در پایتون می پردازیم..
عبارت Extensible Markup Language یا به اختصار XML به معنی زبان نشانه گذاری گسترش پذیر است که یک زبان نشانه گذاری مشابه HTML یا SGML است. کنسرسیوم وب جهان گستر این زبان را به عنوان یک استاندارد سراسری توصیه می کند. چنانچه اپلیکیشنی که قصد طراحی آن را دارید، داده های حجیم و سنگینی برای نگهداری ندارد، در آن صورت می توانید بدون زحمت طراحی دیتابیس و استفاده از پشتوانه ی SQL، اطلاعات برنامه ی خود را در قالب XMLذخیره نمایید.
 
آموزش زبان پایتون : معماری ها و توابع کتابخانه ای تحلیل گر XML Parser
کتابخانه ی استاندارد python تعدادی interface (الگوی پیاده سازی) معدود اما کارا جهت کار با XML در اختیار برنامه نویس قرار می دهد که در زیر به شرح آن ها می پردازیم. دو API و توابع کتابخانه ای پرکاربرد و ساده ای که توصیه می شود عبارتند از :
  • تابع (SAX (Simple API for XML : در این API، توابع Callback ای برای رخدادهای مورد نظر معرفی (register) می کنید و سپس به parser اجازه می دهید به تحلیل باقی فایل بپردازد. ابزار جاری برای شرایطی مفید می باشد که فایل های اپلیکیشن حجیم بوده و شما با محدودیت حافظه مواجه هستید. در واقع API حاضر فایل را از روی دیسک تحلیل و تفسیر می کند و به همین جهت هیچگاه کل فایل در حافظه بارگذاری نشده و آن را اشغال نمی کند.
  • تابع DOM (Document Object Model) : API جاری را کنسرسیوم وب جهان گستر توصیه می کند. در این API کل محتوای فایل داخل حافظه بارگذاری و به صورت درختی یا سلسله مراتبی سازماندهی می شود و کلیه ی ویژگی های یک فایل XML را به نمایش می گذارد.
تابع SAX قادر نیست هنگام کار با فایل های حجیم، اطلاعات را به سرعت DOM پردازش کند. از طرف دیگر، اگر منحصرا از DOM استفاده کنید، به ویژه برای پردازش فایل های کوچک و کم حجم، قطعا میزان قابل توجهی از منابع شما هدر می رود. SAX فایل ها را با مجوز در سطح فقط خواندن باز می کند، در حالی که DOM امکان اعمال تغییرات در فایل XML را فراهم می آورد. از آنجایی که دو API مزبور مکمل یکدیگر هستند، دلیلی وجود ندارد که از هر دو در پروژه های بزرگ استفاده نکنید. نمونه کدهای XML که در مثال های زیر استفاده کرده و به عنوان ورودی توابع پردازش و parse مورد استفاده قرار می دهیم، فایل movies.xml با محتوای زیر خواهد بود :

< collection shelf="New Arrivals">

< movie title="Enemy Behind">
< type>War, Thriller< /type>
< format>DVD< /format>
< year>2003< /year>
< rating>PG< /rating>
< stars>10< /stars>
< description>Talk about a US-Japan war< /description>
< /movie>
< movie title="Transformers">
< type>Anime, Science Fiction< /type>
< format>DVD< /format>
< year>1989< /year>
< rating>R< /rating>
< stars>8< /stars>
< description>A schientific fiction< /description>
< /movie>
< movie title="Trigun">
< type>Anime, Action< /type>
< format>DVD< /format>
< episodes>4< /episodes>
< rating>PG< /rating>
< stars>10< /stars>
< description>Vash the Stampede!< /description>
< /movie>
< type>Comedy< /type>
< format>VHS< /format>
< rating>PG< /rating>
< stars>2< /stars>
< description>Viewable boredom< /description>
< /movie>
< /collection>
 

آموزش Python
 : پردازش و تفسیر XML به وسیله ی توابع SAX
تابع SAX یک interface حاوی مجموعه توابع استاندارد برای تحلیل و پردازش XML به روش رخداد محور (Event-driven) است. جهت استفاده از interface یاد شده برای پردازش و فایل های XML، لازم است با ارث بری (تعریف کلاس مشتق) از xml.sax.ContentHandler، کلاس ContentHandler اختصاصی خود را ایجاد نمایید.
کلاس ContentHandler اختصاصی شما در واقع می تواند تگ ها و attribute های نسخه یا نسخه های مختلف XML را مدیریت نماید. آبجکت ContentHandler تعدادی متد برای مدیریت رخدادهای مختلف parse (پردازش و تحلیل) ارائه می دهد که parser این متدها را به هنگام بارگذاری محتوای فایل XML در حافظه و پردازش آن ها، از ContentHandler فراخوانی می کند.
متدهای startDocument و endDocument هریک به ترتیب در ابتدا و انتهای فایل XML فراخوانی می شوند. اطلاعات و داده های مربوط به کاراکترهای فایل XML از طریق پارامتر text در اختیار متد (character(text قرار می گیرد.
متد ContentHandler در ابتدا و انتهای هر المان فراخوانی می شود. اگر parser در وضعیت namespace mode قرار داشته باشد، در آن صورت متدهای (startElement(tag, attributes و (endElement(tag صدا زده می شوند و در غیر این صورت متدهای مربوطه یعنی startElementNS و endElementNS فراخوانده می شوند. در اینجا منظور از tag در واقع المان tag و attributes، آبجکت Attributes است.
در زیر سایر متدهای مهم که فهم آن ها برای کار با SAX مهم می باشد را مشاهده می کنید :
 
متد جاری یک آبجکت parser جدید ایجاد کرده و آن را در خروجی برمی گرداند. آبجکت parser که در خروجی بازگردانی می شود، اولین نوع parser است که سیستم پیدا می کند.
xml.sax.make_parser( [parser_list] )
در زیر جزئیات پارامترها به تفصیل شرح داده است :
  • پارامتر parser_list : آرگومان اختیاری متشکل از یک لیست از parser ها برای استفاده که تمامی آن ها بایستی متد make_parser را پیاده سازی می کند.

متد زیر یک مفسر و تحلیل گر نحوی SAX تعریف کرده و با استفاده از آن محتوای فایل مورد نظر را parse (تفسیر و تبدیل) می کند.
xml.sax.parse( xmlfile, contenthandler[, errorhandler])
در زیر اطلاعات پارامترهای متد فوق به تفصیل شرح داده شده است :
  • پارامتر xmlfile : این اسم فایل XML است که محتوای آن قرار است خوانده و تفسیر شود.
  • پارامتر contenthandler : آبجکت ساخته شده از کلاس ContentHandler.
  • این پارامتر اختیاری بوده و در صورت استفاده از آن بایستی یک آبجکت ErrorHandler از SAX باشد.
 
آموزش زبان پایتون : متد parseString
متد دیگری که یک تحلیل گر و مفسر SAX ایجاد کرده و رشته ی XML ارسالی را parse می کند، parseString می باشد :
xml.sax.parseString(xmlstring, contenthandler[, errorhandler])
در زیر هریک از پارامتر ها به تفصیل شرح داده شده است :
  • پارامتر xmlstring : اسم رشته ی XML که محتوا از آن خوانده می شود.
  • پارامتر contenthandler : بایستی یک آبجکت ContentHandler باشد.
  • پارامتر errorhandler : پارامتر اختیاری که یک آبجکت ErrorHandler از SAX می باشد.

مثال :
#!/usr/bin/python
import xml.sax
class MovieHandler( xml.sax.ContentHandler ):
   def __init__(self):
      self.CurrentData = ""
      self.type = ""
      self.format = ""
      self.year = ""
      self.rating = ""
      self.stars = ""
      self.description = ""
   # Call when an element starts
   def startElement(self, tag, attributes):
      self.CurrentData = tag
      if tag == "movie":
         print "*****Movie*****"
         title = attributes["title"]
         print "Title:", title
   # Call when an elements ends
   def endElement(self, tag):
      if self.CurrentData == "type":
       print "Type:", self.type
      elif self.CurrentData == "format":
         print "Format:", self.format
      elif self.CurrentData == "year":
         print "Year:", self.year
      elif self.CurrentData == "rating":
         print "Rating:", self.rating
      elif self.CurrentData == "stars":
         print "Stars:", self.stars
      elif self.CurrentData == "description":
         print "Description:", self.description
      self.CurrentData = ""
   # Call when a character is read
   def characters(self, content):
      if self.CurrentData == "type":
         self.type = content
      elif self.CurrentData == "format":
         self.format = content
      elif self.CurrentData == "year":
         self.year = content
      elif self.CurrentData == "rating":
         self.rating = content
      elif self.CurrentData == "stars":
         self.stars = content
      elif self.CurrentData == "description":
         self.description = content
if ( __name__ == "__main__"):
   # create an XMLReader
   parser = xml.sax.make_parser()
   # turn off namepsaces
   parser.setFeature(xml.sax.handler.feature_namespaces, 0)
   # override the default ContextHandler
   Handler = MovieHandler()
   parser.setContentHandler( Handler )
   parser.parse("movies.xml")

خروجی :
*****Movie*****
Title: Enemy Behind
Type: War, Thriller
Format: DVD
Year: 2003
Rating: PG
Stars: 10
Description: Talk about a US-Japan war
*****Movie*****
Title: Transformers
Type: Anime, Science Fiction
Format: DVD
Year: 1989
Rating: R
Stars: 8
Description: A schientific fiction
*****Movie*****
Title: Trigun
Type: Anime, Action
Format: DVD
Rating: PG
Stars: 10
Description: Vash the Stampede!
*****Movie*****
Title: Ishtar
Type: Comedy
Format: VHS
Rating: PG
Stars: 2
Description: Viewable boredom
 

آموزش Python
 :
 پردازش و تفسیر فایل های XML با استفاده از توابع DOM
مدل شی گرای فایل (Document Object Model) یا به اختصار DOM یک API و مجموع توابع کتابخانه ای است که کنسرسیوم وب جهان گستر برای دسترسی و ویرایش محتوای فایل های XML، به توسعه دهندگان توصیه می کند. DOMبه ویژه برای اپلیکیشن هایی که لازم است به محتوای فایل XML آن به صورت رندوم دسترسی صورت گیرد، مفید می باشد. SAX به توسعه دهنده امکان دسترسی فقط به یک قسمت از فایل XML را در آن واحد می دهد. به طور مثال، هنگام دسترسی به یک المان از فایل XML، امکان دسترسی به سایر المان های فایل برای شما وجود ندارد.
ماژول xml.dom، به شما این امکان را می دهد تا یک آبجکت minidom ایجاد کرده و محتوای فایل XML را به سرعت در حافظه بارگذاری نمایید. آبجکت minidom متد کارا و ساده تری جهت ساخت درخت DOM از فایل XML در اختیار توسعه دهنده قرار می دهد.
نمونه کد زیر متد ([parse(file [,parser از آبجکت minidom را صدا زده و محتوای فایل XML را تجزیه و به آبجکت درخت DOM تبدیل می کند.

مثال :
#!/usr/bin/python
from xml.dom.minidom import parse
import xml.dom.minidom
# Open XML document using minidom parser
DOMTree = xml.dom.minidom.parse("movies.xml")
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
   print "Root element : %s" % collection.getAttribute("shelf")
# Get all the movies in the collection
movies = collection.getElementsByTagName("movie")
# Print detail of each movie.
for movie in movies:
   print "*****Movie*****"
   if movie.hasAttribute("title"):
      print "Title: %s" % movie.getAttribute("title")
   type = movie.getElementsByTagName('type')[0]
   print "Type: %s" % type.childNodes[0].data
   format = movie.getElementsByTagName('format')[0]
   print "Format: %s" % format.childNodes[0].data
   rating = movie.getElementsByTagName('rating')[0]
   print "Rating: %s" % rating.childNodes[0].data
   description = movie.getElementsByTagName('description')[0]
   print "Description: %s" % description.childNodes[0].data

خروجی :
Root element : New Arrivals
*****Movie*****
Title: Enemy Behind
Type: War, Thriller
Format: DVD
Rating: PG
Description: Talk about a US-Japan war
*****Movie*****
Title: Transformers
Type: Anime, Science Fiction
Format: DVD
Rating: R
Description: A schientific fiction
*****Movie*****
Title: Trigun
Type: Anime, Action
Format: DVD
Rating: PG
Description: Vash the Stampede!
*****Movie*****
Title: Ishtar
Type: Comedy
Format: VHS
Rating: PG
Description: Viewable boredom
 
با دیگر مقالات آموزش پایتون همراه ما باشید..

آموزش ارسال ایمیل با پایتون

۳۹ بازديد
در این مقاله به آموزش ارسال ایمیل با پایتون و چگونگی استفاده از SMTP در پایتون را با یکدیگر مورد بررسی قرار می دهیم..
 

آموزش پایتون
: فرستادن ایمیل با SMTP در پایتون
عبارت Simple Mail Transfer Protocol یا به اختصار SMPT (پروتکل ارسال و انتقال ایمیل) معرفی پروتکلی است که ارسال ایمیل و آدرس دهی (routing) آن بین سرویس دهنده های ایمیل را مدیریت می کند.
پایتون ماژولی به نام smtplib در اختیار توسعه دهنده قرار می دهد که یک آبجکت حاوی اطلاعات session ( اطلاعات جلسه ی کاری کاربر یا client session object) را در خود به صورت کپسوله داشته و می توان از آن برای ارسال ایمیل به هر دستگاه آنلاینی که listener daemon (برنامه ی ای که به رخدادها گوش داده و در پس زمینه فعالیت می کند) SMTP یا ESMTP بر روی آن فعال است، استفاده نمود. در زیر نحوه ی ساخت یک آبجکت SMTP ساده که بعده ها جهت ارسال ایمیل مورد استفاده قرار می گیرد، را مشاهده می کنید :
import smtplib
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
 

در زیر شرح کاربرد هر یک از پارامترهای عنوان شده در قطعه کد بالا را مشاهده می کنید :
  • پارامتر host : پارامتر جاری همان میزبان یا هاستی است که به عنوان سرویس دهنده ی SMTP شما ایفای نقش می کند (SMTP server شما بر روی آن اجرا می شود). شما می توانید مقدار این پارامتر را آدرس IP میزبان یا اسم دامنه همچون tahlildadeh.com تنظیم نمایید. استفاده از این آرگومان اختیاری است.
  • پارامتر port : در صورت مقداردهی آرگومان اول، لازم است یک پورت یا شماره ی درگاه نیز مشخص نمایید که SMPT Server به آن گوش می دهد. شماره ی این پورت معمولا 25 می باشد.
  • پارامتر local_hostname : چنانچه SMPT Server شما بر روی دستگاه محلی (کامپیوتر شخصی) مستقر و فعال باشد، در آن صورت کافی است مقدار این پارامتر را localhost قرار دهید.

در آبجکت SMPT متدی تعبیه شده به نام sendmail که اغلب، توسعه دهنده با استفاده از آن کار عملیات ارسال پیغام مورد نظر را به انجام می رساند. متد نام برده در کل سه پارامتر ورودی دریافت می کند که به شرح زیر می باشند :
  • پارامتر sender : یک مقدار رشته ای دربردارنده آدرس ارسال کننده پیغام.
  • پارامتر receivers : لیستی از رشته ها که هریک مختص به دریافت کننده ی مجزا می باشد.
  • پارامتر message : یک پیغام به صورت رشته و فرمت دهی شده بر اساس مشخصات و قواعد RFC ها.

مثال :
در زیر یک اسکریپت ساده پایتون را مشاهده می کنید که ایمیلی را ارسال می کند.
#!/usr/bin/python
import smtplib
sender = 'from@fromdomain.com'
receivers = ['to@todomain.com']
message = """From: From Person
To: To Person
Subject: SMTP e-mail test
This is a test e-mail message.
"""
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message)
print "Successfully sent email"
   except SMTPException:
   print "Error: unable to send email"
 
در تمرین جاری، یک ایمیل ساده داخل متغیر message و کوتیشن سه تایی درج گردید و همان طور که می بینید، هدرها به روش صحیح فرمت دهی شده اند. هر ایمیل، سه هدر به ترتیب From ،To و Subject که به وسیله ویرگول از هم و به وسیله خط سفید از بدنه پیغام جدا شده اند را شامل می شود.
به منظور ارسال ایمیل، ابتدا با استفاده از smtpObj به SMPT Server (سرویس دهنده ی سرور) مستقر بر روی دستگاه محلی (local) وصل شوید، سپس متد sendmail را فراخوانی کرده و پیغام، آدرس فرم و آدرس مقصد را به عنوان پارامتر به این متد ارسال نمایید (اگرچه فرم و آدرس داخل خود ایمیل گنجانده شده، با این حال از این مقدارها همیشه برای آدرس دهی یا route ایمیل استفاده نمی شود).
چنانچه شما برای ارسال ایمیل از SMPT Server که بر روی دستگاه شما (local) شما نصب و اجرا شده، استفاده نمی کنید، در آن صورت می توانید با استفاده از smtplib client به یک سرور SMPT راه دور متصل شوید. برای این منظور لازم است ارائه دهنده ی ایمیل جزئیات و اطلاعات mail server خروجی دهنده را در اختیار شما قرار داده باشد و شما نیز آن ها را به صورت زیر بکار ببرید، مگر اینکه برای ارسال ایمیل از یک سرویس آماده همچون Hotmail و Yahoo استفاده نمایید که در آن صورت نیازی به این اطلاعات نیست.
smtplib.SMTP('mail.your-domain.com', 25)
 

آموزش Python : ارسال فایل ایمیل به صورت HTML با استفاده از Python
زمانی که توسعه دهنده یک پیغام متنی را با استفاده از Python ارسال می کند، تمامی محتوای فایل به عنوان متن ساده در نظر گرفته می شود. به عبارت دیگر حتی اگر تگ های HTML را در پیغام متنی بگنجانید، باز هم محتوای فایل به صورت متن ساده نمایش داده شده و تگ های HTML بر اساس گرامر زبان نشانه گذاری HTML فرمت دهی نمی شوند. پایتون امکانی را در اختیار توسعه دهنده قرار می دهد که به واسطه ی آن می توان یک پیغام HTML را به صورت یک فایل واقعی HTML ارسال کرد.
به هنگام ارسال یک ایمیل، می توان نوع فایل (Mime version)، نوع محتوا و مجموعه کاراکتری که باید به صورت یک ایمیل HTML ارسال شود را مشخص نمایید.

مثال :
در زیر کدی را مشاهده می کنید که محتوایی با فرمت HTML را به صورت ایمیل ارسال می کند :
#!/usr/bin/python
import smtplib
message = """From: From Person
To: To Person
MIME-Version: 1.0
Content-type: text/html
Subject: SMTP HTML e-mail test
This is an e-mail message to be sent in HTML format
< b>This is HTML message.< /b>
< h1>This is headline.< /h1>
"""
try:
   smtpObj = smtplib.SMTP('localhost')
   smtpObj.sendmail(sender, receivers, message)   
   print "Successfully sent email"
except SMTPException:
   print "Error: unable to send email"
 
 
آموزش برنامه نویسی پایتون : ارسال محتوا همراه با ایمیل در پایتون
جهت ارسال ایمیل با محتوای مختلط، لازم است مقدار هدر Content-type را برابر multipart/mixed قرار دهید. پس از آن، متن و محتوای الصاقی (attachment) را در boundaries دقیقا اعلان کنید. برای تعریف boundary، دو خط تیره (هایفن) و یک عدد منحصربفرد درج کنید که این بخش نباید در بدنه ی ایمیل یا بخش پیغام ظاهر شود. سپس یک boundary نهایی درج می کنید که نشانگر بخش پایانی ایمیل بوده و باید به دو خط تیره ختم شود. فایل های الصاق شده باید قبل از ارسال، به وسیله ی تابع pack("m") بر مبنای الگوریتم و روش کدگذاری base64 رمزنگاری شوند.

مثال :
در مثال زیر، فایل /tmp/test.txt به عنوان محتوای الصاقی همراه با ایمیل ارسال می شود :
#!/usr/bin/python
import smtplib
import base64
filename = "/tmp/test.txt"
# Read a file and encode it into base64 format
fo = open(filename, "rb")
filecontent = fo.read()
encodedcontent = base64.b64encode(filecontent)  # base64
sender = 'webmaster@tutorialpoint.com'
reciever = 'amrood.admin@gmail.com'
marker = "AUNIQUEMARKER"
body ="""
This is a test email to send an attachement.
"""
# Define the main headers.
part1 = """From: From Person
To: To Person
Subject: Sending Attachement
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=%s
--%s
""" % (marker, marker)
# Define the message action
part2 = """Content-Type: text/plain
Content-Transfer-Encoding:8bit
%s
--%s
""" % (body,marker)
# Define the attachment section
part3 = """Content-Type: multipart/mixed; name="%s"
Content-Transfer-Encoding:base64
Content-Disposition: attachment; filename=%s
%s
--%s--
""" %(filename, filename, encodedcontent, marker)
message = part1 + part2 + part3
try:
   smtpObj = smtplib.SMTP('localhost')
   smtpObj.sendmail(sender, reciever, message)
   print "Successfully sent email"
except Exception:
   print "Error: unable to send email"
 
با دیگر مقاله های ما در زمینه آموزش پایتون همراه ما باشید...