Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Extending and Embedding Python

Extending and Embedding Python

Vladimir Pouzanov

January 30, 2010
Tweet

More Decks by Vladimir Pouzanov

Other Decks in Programming

Transcript

  1. CPython (Stackless) Jython IronPython Java DLR CLR C C++ CPython

    API Pyrex/ Cython SWIG boost SIP Objective-C Java VM .NET
  2. CPython Îñîáåííîñòè ðàçðàáàòûâàåòñÿ Python Software Foundation êëàññè÷åñêàÿ ðåàëèçàöèÿ, èñïîëçóåòñÿ ïî÷òè

    ïîâñþäó ðåàëèçîâàí íà Ñè êàê èíòåðïðåòàòîð áàéòêîäà åäèíñòâåííûé ðåàëèçóåò âåñü ôóíêöèîíàë Python ëèöåíçèÿ: GPL 2 Íåäîñòàòêè GIL  Global Interpreter Lock
  3. CPython-stackless Ïîäâèä CPython, Stackless ââîäèò â Python ïëàíèðîâùèê ìèêðîïîòîêîâ 

    äåøåâûõ è ëåãêèõ. Ýòî ïîçâîëÿåò óëó÷øèòü ñòðóêòóðó êîäà ñäåëàòü åãî áîëåå ÷èòàåìûì óâåëè÷èòü ïðîäóêòèâíîñòü ïðîãðàììèñòà Îñíîâíûå îòëè÷èÿ Ìèêðîïîòîêè  òàñêëåòû Òàñêëåòû ïðåäñòàâëÿþò ñîáîé îáåðòêè âîêðóã ôóíêöèé äëÿ èõ çàïóñêà êàê â âèäå ìèêðîïîòîêîâ Êàíàëû Êàíàëû èñïîëüçóþòñÿ äëÿ äâóñòîðîííåé ñâÿçè ìåæäó òàñêëåòàìè Ïëàíèðîâùèê Êàðóñåëüíûé ïëàíèðîâùèê ïîçâîëÿåò ïëàíèðîâàòü òàñêëåòû êàê êîîïåðàòèâíî, òàê è âûãðóæàåìî Ñåðèàëèçàöèÿ Òàñêëåòû ìîæíî ñåðèàëèçîâàòü (÷åðåç pickle) íà äèñê, äëÿ èõ äàëüíåéøåãî âîçîáíîâëåíèÿ
  4. CPython-stackless  ïðèìåð >>> import stackless >>> channel = stackless.channel()

    >>> def receiving_tasklet(): ... print "Recieving tasklet started" ... print channel.receive() ... print "Receiving tasklet finished" ... >>> def sending_tasklet(): ... print "Sending tasklet started" ... channel.send("send from sending_tasklet") ... print "sending tasklet finished" ... >>> def another_tasklet(): ... print "Just another tasklet in the scheduler" ... >>> stackless.tasklet(receiving_tasklet)() <stackless.tasklet object at 0x00A45B30> >>> stackless.tasklet(sending_tasklet)() <stackless.tasklet object at 0x00A45B70> >>> stackless.tasklet(another_tasklet)() <stackless.tasklet object at 0x00A45BF0> >>> stackless.run() Recieving tasklet started Sending tasklet started send from sending_tasklet Receiving tasklet finished Just another tasklet in the scheduler sending tasklet finished
  5. Jython Ïîëíîöåííàÿ ðåàëèçàöèÿ èíòåðïðåòàòîðà Python íà áàçå Java VM. Äèíàìè÷åñêàÿ

    êîìïèëÿöèÿ â Java-áàéòêîä  ìàêñèìàëüíàÿ ïðîèçâîäèòåëüíîñòü ïðè ñîõðàíåíèè èíòåðàêòèâíîñòè âîçìîæíîñòü ðàñøèðåíèÿ Javaêëàññîâ ïîçâîëÿåò ýôôåêòèâíî èñïîëüçîâàòü àáñòðàêòíûå êëàññû îïöèîíàëüíàÿ ñòàòè÷åñêàÿ êîìïèëÿöèÿ  âîçìîæíîñòü èñïîëüçîâàíèÿ â ñåðâëåòàõ, àïïëåòàõ, è ò.ä. ñèíòàêñèñ Python îáúåäèíÿåò ïîðàçèòåëüíóþ ìîùü ñ ïðîñòûì ñèíòàêñèñîì; ïîëíîâåñíàÿ îáúåêòíàÿ ìîäåëü îòëè÷íî âïèñûâàåòñÿ â äèçàéí ÎÎÏ Java.
  6. IronPython ðåàëèçàöèÿ Python äëÿ CLR (Common Language Runtime) ñ èñïîëüçîâàíèåì

    ìàøèíû .NET èíòåãðàöèÿ ñ òåõíîëîãèÿìè òèïà MS Silverlight ðàçðàáàòûâàåòñÿ Microsoft ëèöåíçèÿ: MSPL ÷àñòè÷íî ïîääåðæèâàåòñÿ Mono
  7. ìîäóëè íà C Èñïîëüçóåòñÿ Python API ñïîñîá âçàèìîäåéñòâèÿ ñ èíòåðïðåòàòîðîì

    íàïðÿìóþ âñ¼ áðåìÿ óïðàâëåíèÿ Python-îáúåêòàìè ïàäàåò íà ïðîãðàììèñòà áîëüøå âîçìîæíîñòåé äîñòóïà âî ¾âíåøíèé ìèð¿
  8. static PyMethodDef ifconfig_methods[] = { /* ... */ { "ieee80211_status",

    ifconfig_ieee80211_status, METH_VARARGS, "ieee80211_status(ifname)\n" }, { "setifaddr", (PyCFunction)setifaddr, METH_VARARGS | METH_KEYWORDS, "setifaddr(ifname, addr, netmask='', broadcast='',\n" " dst='', alias=False, delete=False)\n\n" "Set the given address addr to interface ifname.\n" "Only AF_INET family is supported at the moment.\n\n" "broadcast and dst are exclusive (the same)\n" }, {NULL, NULL, NULL, NULL}, }; PyMODINIT_FUNC initifconfig(void) { Py_InitModule("ifconfig", ifconfig_methods); }
  9. static PyObject * ifconfig_ieee80211_status(PyObject *self, PyObject *args) { PyObject *status;

    char *ifname; struct ieee80211_nwid nwid; if (PyArg_ParseTuple(args, "s", &ifname) == NULL) return (NULL); if ((status = PyDict_New()) == NULL) return (PyErr_NoMemory()); /* nwid */ memset(&ifr, 0, sizeof(ifr)); ifr.ifr_data = (caddr_t)&nwid; strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr); if (inwid == 0) { /* nwid.i_nwid is not NULL terminated. */ obj = PyString_FromStringAndSize(nwid.i_nwid, nwid.i_len > IEEE80211_NWID_LEN ? IEEE80211_NWID_LEN : nwid.i_len); PyDict_SetItemString(status, "nwid", obj); Py_XDECREF(obj); } /* ... */ return (status); }
  10. static PyObject * ifconfig_ifstatus(PyObject *self, PyObject *args) { int s;

    struct ifreq *ifr; PyObject *mediadict, *inetlist, *status; /* description */ bzero(ifr, sizeof(*ifr)); strlcpy(ifr->ifr_name, ifname, sizeof(ifr->ifr_name)); ifr->ifr_data = (caddr_t)&ifdescr; ioctl(s, SIOCGIFDESCR, (caddr_t)ifr); obj = PyString_FromString(ifdescr); PyDict_SetItemString(status, "description", obj); Py_XDECREF(obj); return (status); postifaddrserror: postmediaerror: Py_XDECREF(mediadict); error: Py_XDECREF(inetlist); Py_XDECREF(status); free(ifr); close(s); PyErr_SetFromErrno(PyExc_OSError); return (NULL); }
  11. Ñáîðêà .include "../Makefile.inc" .MAIN: build .SUFFIXES: .c .so NET= __init__.py

    autoconf.py ifconfig.so interface.py var.py DEBUG= -g -DDEBUG CPPFLAGS= -I/usr/local/include -I/usr/local/include/python2.6 LDFLAGS= -L/usr/local/lib -L/usr/local/lib/python2.6 build: ${NET} .c.so: cc ${DEBUG} -fPIC -shared ${CPPFLAGS} ${LDFLAGS} \ $< -o $@
  12. ctypes âñòðîåííûé â Python ìîäóëü äëÿ äîñòóïà ê C-ôóíêöèÿì âî

    âíåøíèõ áèáëèîòåêàõ. Ïðåäîñòàâëÿåò òèïû õðàíåíèÿ, ñîâìåñòèìûå ñ C. Ìîæíî èñïîëüçîâàòü äëÿ ãåíåðàöèè èíòåðôåéñîâ ê áèáëèîòåêàì íà C ñ ïîìîùüþ Python-only êîäà.
  13. pyrex/cython pyrex ïîçâîëÿåò ïèñàòü ñìåøàííûé C/Python ïñåâäîêîä ìîæíî èñïîëüçîâàòü òèïû

    äàííûõ êàê Python, òàê è C òðàíñëèðóåò êîä â C-ìîäóëü cython ïðîäîëæåíèå ïðîåêòà pyrex áûñòðûé ïîääåðæêà íåêîòîðûõ âîçìîæíîñòåé Ñ++
  14. pyrex/cython  ïðèìåð import sys import evas.c_evas cimport evas.c_evas as

    c_evas cimport evas.python import traceback def init(): cdef int argc, i, arg_len cdef char **argv, *arg argc_orig = argc = len(sys.argv) argv = <char **>PyMem_Malloc(argc * sizeof(char *)) for i from 0 <= i < argc: arg = sys.argv[i] arg_len = len(sys.argv[i]) argv[i] = <char *>PyMem_Malloc(arg_len + 1) memcpy(argv[i], arg, arg_len + 1) elm_init(argc, argv) include "elementary.c_elementary_object.pxi" # ...
  15. swig Èíñòðóìåíò äëÿ ãåíåðàöèè áèíäèíãîâ C/C++ êîäà íà ñêðèïòîâûå ÿçûêè:

    Perl, PHP, Python, Tcl, Ruby. Îòëè÷íî ïîäõîäèò äëÿ òåñòèðîâàíèÿ è ïðîòîòèïèðîâàíèÿ êîäà. /* example.i */ %module example %{ /* Put header files here or function declarations like below */ extern double My_variable; extern int fact(int n); extern int my_mod(int x, int y); extern char *get_time(); %} extern double My_variable; extern int fact(int n); extern int my_mod(int x, int y); extern char *get_time();
  16. boost::python, SIP boost::python (http://www.boost.org) ïîçâîëÿåò ýôôåêòèâíî âçàèìîäåéñòâîâàòü ñ Python èç

    êîäà íà C++ ïîääåðæêà ññûëîê è óêàçàòåëåé ðåãèñòðàöèÿ ïðèâåäåíèÿ òèïîâ àâòîìàòè÷åñêèå êðîññìîäóëüíûå ïðèâåäåíèÿ òèïîâ ýôôåêòèâíàÿ ïåðåãðóçêà ôóíêöèé òðàíñëÿöèÿ èñêëþ÷åíèé èç C++ â Python àðãóìåíòûêëþ÷è è àðãóìåíòû ïî óìîë÷àíèþ ìàíèïóëÿöèÿ îáúåêòàìè Python èç C++ àâòîìàòè÷åñêèé ýêñïîðò èòåðàòîðîâ C++ â èòåðàòîðû Python ýôôåêòèâåí äëÿ âñòðàèâàíèÿ èíòåðïðåòàòîðà â êîä SIP îòíîñèòåëüíî ëåãêèå è áûñòðûå ìåòîäû ñîçäàòü îáåðòêè êîäà C++ äëÿ Python ñèíòàêñè÷åñêè ïîõîæ íà swig success story: Qt (PyQt)
  17. boost::python  ïðèìåð BOOST_PYTHON_MODULE(libboopyclass) { boost::python::class_<World>("World") .def("greet", &World::greet) .def("set", &World::set);

    boost::python::class_<PlusOne>("PlusOne") .def("func", &PlusOne::func); boost::python::class_<Var>("Var", boost::python::init<std::string>()) .def_readonly("name", &Var::name) .def_readwrite("value", &Var::value); boost::python::class_<Num>("Num") .add_property("rovalue", &Num::get) .add_property("value", &Num::get, &Num::set); boost::python::class_<BaseWrap1, boost::noncopyable>("Base1") .def("f", boost::python::pure_virtual(&Base1::f)); boost::python::class_<BaseWrap2, boost::noncopyable>("Base2") .def("f", &Base2::f, &BaseWrap2::default_f); }
  18. Èíúåêöèÿ è èññëåäîâàíèå â êîä íà C/C++ ñ äîñòóïîì ê

    C-ôóíêöèÿì èç âíåøíèõ áèáëèîòåê (ctypes, API) hacking! â êîä íà Java (jython) â êîä íà C# (ironpython) â êîä íà Objective-C ñ ïîëíûì äîñòóïîì ê îáúåêòíîìó ðàíòàéìó (pyobjc)
  19. pyobjc Áèíäèíãè íà Objective-C ïîçâîëÿþò ïîëó÷èòü ïîëíûé äîñòóï ê òåêóùåìó

    îêðóæåíèþ ðàíòàéìà èç Python, êóäà áóäóò îòîáðàæåíû âñå ñóùåñòâóþùèå êëàññû. Äîñòóï êî âñåì îñíîâíûì ôðåéìâîðêàì íà OSX/iPhoneOS âîçìîæíîñòü íàïèñàíèÿ ïîëíîôóíêöèîíàëüíûõ ïðîãðàìì èñïîëüçóÿ òîëüêî Python èññëåäîâàíèå objcðàíòàéìà â äðóãèõ ïðîöåññàõ
  20. >>> app = NSApplication.sharedApplication() >>> print app.windows() ( "<BrowserWindow: 0x11546a030>",

    "<NSPanel: 0x11543a110>", "<MHOSuggestionWindow: 0x11543de60>", "<NSPanel: 0x1154648a0>", "<NSPanel: 0x115435ad0>", "<NSWindow: 0x115c4d5e0>", "<NSWindow: 0x11f188f40>", "<FSObjectBrowser: 0x11f18afd0>", "<WebTextInputPanel: 0x11f5bbee0>", "<NSWindow: 0x11ef6b7e0>" ) >>> win = app.windows()[0] >>> controller = win.delegate() >>> doc = controller.document() >>> print controller, doc <BrowserWindowController: 0x11545c560> <BrowserDocument: 0x115c6a790> >>> frame = doc._selectedFrameView() >>> webView = frame._webView() >>> evl = lambda x: webView.stringByEvaluatingJavaScriptFromString_(x) >>> evl('alert("Double bridged string ^_^")') >>> evl('document.getElementsByClassName("pageheading")[0].innerHTML = "Python was here!"')