Python dla naukowca Ext Emb

background image

J

ĘZYK

PYTHON

-

NARZĘDZIE

DLA

KAŻDEGO

NAUKOWCA

Marcin Lewandowski

[

mlew@ippt.gov.pl

]

background image

ROZSZERZANIE I OSADZANIE PYTHONA
(PYTHON EXTENDING & EMBEDDING)

2

background image

Łączenie i Osadzanie Pythona

• Łączenie Pythona (Extending)

– Tworzenie wrapperów do bibliotek w C/C++

• Osadzanie Pythona (Embedding)

– Wywoływanie Pythona z programu C/C++

3

background image

PO CO?

Budowa „skryptowalnych” aplikacji C/C++ – nie tylko

bibliotekę C/C++, ale całą aplikację można zamienid na

moduł Pythona. Zastępując main() programu C/C++ przez

interpreter Pythona uzyskujemy aplikację kontrolowaną

skryptem Pythona! To pozwala łatwą modyfikację aplikacji

(bez konieczności jej rekompilacji).

Szybkie prototypowanie i debugowanie

biblioteka/aplikacja C/C++ pod kontrolą Pythona może byd

łatwo testowana i debugowana.

Integracja systemów/oprogramowania – z pomocą

Pythona i modułów rozszerzeo można łatwo sklejad

aplikacje i biblioteki stworzone w różnych językach (nie

tylko C/C++). Niezależne elementy aplikacje i biblioteki

można integrowad w jedną nową aplikację.

4

background image

Zagadnienia łączenia różnych języków

programowania

• typy danych
• przekazywanie argumentów funkcji
• tworzenie nowych zmiennych
• zarządzanie pamięcią
• obsługa wyjątków

5

background image

LINKI

• Extending and Embedding the Python

Interpreter – dokumentacja Pythona
(

http://docs.python.org/extending/

)

• Python/C API – interfejs C do Pythona

(

http://docs.python.org/c-api/

)

6

background image

ROZSZERZANIE PYTHONA

7

background image

Kompilacja rozszerzenia do Pythona

Rozszerzenie (moduł C) można łączyd z

Pythonem przez:

– Ładowanie dynamiczne

• Rozszerzenie jest kompilowane do biblioteki współdzielonej

(DLL).

• Polecenie ‘import’ ładuje i inicjalizuje moduł w locie
• Łatwiejsza kompilacja i stosowane częściej niż łączenie

statyczne

– Łączenie statyczne

• Rozszerzenie jest wkompilowane bezpośrednio w interpreter

Pythona i staje się nowym modułem wbudowanym (“built-

in”)

• Polecenie ‘import’ tylko inicjalizuje moduł

8

background image

Python/C API

(plik nagłówkowy Python.h)

The Very High Level Layer

Reference Counting

Exception Handling

Utilities

– Operating System Utilities
– System Functions
– Process Control
– Importing Modules
– Data marshalling support
– Parsing arguments and building values
– String conversion and formatting
– Reflection

Abstract Objects Layer

– Object Protocol
– Number Protocol
– Sequence Protocol
– Mapping Protocol
– Iterator Protocol
– Old Buffer Protocol

Concrete Objects Layer

Fundamental Objects

Numeric Objects

Sequence Objects

Mapping Objects

Other Objects

Initialization, Finalization, and Threads

Thread State and the Global Interpreter Lock

Profiling and Tracing

Advanced Debugger Support

Memory Management

Object Implementation Support

Allocating Objects on the Heap

Common Object Structures

Type Objects

Number Object Structures

Mapping Object Structures

Sequence Object Structures

Buffer Object Structures

Supporting Cyclic Garbage Collection

9

background image

Funkcja opakowująca (wrapper)

Argumenty z

Pythona

• Konwersja argumentów na typy C
• Weryfikacja poprawności argumentów

Funkcja

• Wykonanie funkcji na przekazanych

argumentach

Rezultaty do

Pythona

• Konwersja rezultatów funkcji do Pythona
• Ustawienie Ref Count zwracanych obiektów

10

background image

Konwersja typów C->Python

PyObject *Py_BuildValue(char *format, ...)

– Tworzy obiekt Pythona z listy zmiennych C na

podstawie stringu określającego format (a’la
printf())

– Typ PyObject jest uniwersalnym typem służącym

do wymiany zmiennych/obiektów pomiędzy C i
Pythonem

11

background image

Konwersja typów Python->C

int PyArg_ParseTuple(PyObject *args, char *format, ...)

– Służy do konwersji zmiennych/obiektów Pythona do C

na podstawie stringu określającego format (a’la
scanf())

PyObject *args jest obiektem interpretera Python

zawierającym argumenty przekazane do funkcji

int PyArg_ParseTupleAndKeywords(PyObject *args,

PyObject *kw, const char *format, char *keywords[], ...)

– j.w. ale z opcją interpretacji argumentów nazwanych

(keyword) do funkcji

12

background image

Tworzenie nowych

zmiennych/obiektów Pythonowych

Funkcja tworząca
(zwraca obiekt typu PyObject* do Python/C)

Wartośd Pythonowa

Py_BuildValue("“)

None

Py_BuildValue("i", 123)

123

Py_BuildValue("iii", 123, 456, 789)

(123, 456, 789)

Py_BuildValue("s", "hello")

'hello'

Py_BuildValue("ss", "hello", "world")

('hello', 'world')

Py_BuildValue("s#", "hello", 4)

‘hell’

Py_BuildValue("()")

()

Py_BuildValue("(ii)", 123, 456)

(123, 456)

Py_BuildValue("[i,i]", 123, 456)

[123, 456]

Py_BuildValue("{s:i,s:i}", "abc", 123, "def", 456)

{'abc': 123, 'def': 456}

Py_BuildValue("((ii)(ii)) (ii)", 1, 2, 3, 4, 5, 6)

(((1, 2), (3, 4)), (5, 6))

13

background image

Mechanizm zarządzenia pamięcią

Python/C

• Każdy obiekt/zmienna Pythona ma licznik odwołao (referencji)

zwiększany przy każdym przypisaniu

• Gdy licznik jest równy zero obiekt jest automatycznie usuwany z

pamięci (tzw. Automatic Garbage Collection)

• W kodzie C/C++ trzeba SAMEMU aktualizowad licznik!
• Zwiększenie licznika:

void Py_INCREF(PyObject *o)

• Zmniejszanie licznika:

void Py_DECREF(PyObject *o)

• Zwracanie nowo utworzonego w C obiektu do Pythona:

res = Py_BuildValue("i", 1234);
Py_INCREF(res);
return res;

14

background image

Reguły własności obiektów Python

• Każde wywołanie Py_INCREF() powinno ostatecznie byd sparowane z

wywołaniem Py_DECREF()

• Py_INCREF() służy do „zabezpieczenia” życia obiektu na czas jego używania

przez funkcję; czasami korzysta się z „pożyczonych” referencji

• Większośd (ALE NIE WSZYSTKIE!) funkcji Python/C API wykonuje INCREF

na zwracanych/tworzonych obiektach; w takim wypadku funkcja

wywołująca jest odpowiedzialna za wykonanie Py_DECREF()

• Nie ma konieczności INCREF dla każdej zmiennej lokalnej O ILE nie ma

szansy, że w tym czasie ktoś inny wykona DECREF

• Większośd funkcji zakłada, że przekazane argumenty (obiekty) są już

„zabezpieczone”, więc nie wykonuje dla nich INCREF

• WYJĄTKI:

– PyTuple_SetItem() i PyList_SetItem() – przejmują z założenia argumenty

„niezabezpieczone”

– PyTuple_GetItem() – nie wykonuje INCREF na zwracanych obiektach
– i jeszcze inne – patrz dokumentacja!!!

15

background image

Obsługa i raportowanie błędów

• Moduły rozszerzeo zwracają błąd do Pythona przez

zwrot wartości NULL

• Dodatkowo przed powrotem do interpretera funkcja C

powinna ustawid typ błędu np.:

void PyErr_NoMemory() – wyjątek typu MemoryError
void PyErr_SetFromErrno(PyObject *exc) – wyjątek z

błędem ustalonym na podstawie wartości errno biblioteki

CRT

void PyErr_SetObject(PyObject *exc, PyObject *val)

wyjątek typu exc wraz z obiektem obiekt/wartością

wyjątku val

void PyErr_SetString(PyObject *exc, char *msg) – wyjątek

typu exc wraz ze stringiem msg komunikatu błędu

16

background image

Szkielet modułu rozszerzającego

#include <Python.h>

static PyObject * spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
sts = system(command);
return Py_BuildValue("i", sts);
}

static PyMethodDef SpamMethods[] = {
{"system", spam_system, METH_VARARGS, "Execute a shell command."},
{NULL, NULL, 0, NULL} /* Sentinel */
};

PyMODINIT_FUNC
initspam(void)
{
(void) Py_InitModule("spam", SpamMethods);
}

17

background image

Konwencja C

• Nazywanie modułów C – nazwą z

podkreśleniem (np. _module.pyd/_module.so)

• Obudowanie modułu C modułem Pythona:

# module.py
from _module import *
# Dodatkowy kod wspierający poniżej…
. . .

18

background image

Ręczna kompilacja modułu C

• Niestety polecenia kompilacji są nieco różna

dla różnych systemów operacyjnych

– np. pod LINUX:

> gcc -fpic -c -I/usr/local/include/python \
-I/usr/local/lib/python/config \
example.c wrapper.c
> gcc -shared example.o wrapper.o -o

examplemodule.so

19

background image

Kompilacja rozszerzeo za pomocą

modułu distutils

• Plik setup.py zawiera: pythonowy moduł obudowujący

example.py oraz kod źródłowy C: pyexample.c, example.c:

# setup.py
from distutils.core import setup, Extension
setup(name="example",
version="1.0",
py_modules = ['example.py'],
ext_modules = [ Extension("_example",

["pyexample.c","example.c"]) ]

)

• Kompilacja modułu za pomocą polecenia:

% python setup.py build
% python setup.py install

20

background image

Generatory interfejsów

SWIG (Simplified Wrapper Interface Generator) –

automatyczny generator wrapper’ów C/C++ dla
języków dynamicznych Guile, Java, Mzscheme, Ocaml,
Perl, Pike, PHP, Python, Ruby, and Tcl (

www.swig.org

).

SIP – generator interfejsów Python/C++; koncepcyjnie

podobny do SWIG; używany do budowy interfejsów
PyQt i PyKDE.

F2PY – generator interfejsów Fortran/C/Python;

moduły C są generowane na podstawie plików sygnatur
(.pyf) z kodu Fortran/C (

http://www.scipy.org/F2py

).

21

background image

Biblioteki Python/C/C++

PyCXX – obiektowa biblioteka do budowy

rozszerzeo do Pythona w C++
(

http://sourceforge.net/projects/cxx

)

Boost.Python – elegancka biblioteka obiektowa

zapewniająca integrację klas, funkcji i obiektów
C++ i Pythona (

www.boost.org

)

ctypes – moduł Pythona umożliwia bezpośrednie

wołanie funkcji w bibliotekach dynamicznych;
zapewnia obsługę typów danych C oraz
konwencję wywołao.

22

background image

Inne rozwiązania

Weave – element pakietu SciPy pozwala na

umieszczanie kodu C/C++ bezpośrednio w kodzie
Pythona w celu jego akceleracji
(

http://www.scipy.org/Weave

)

Pyrex – jest Pythonem z typami danych języka C

(cdef); umożliwia kompilację takiego kodu do
modułu C (coś jak Python2C)

Psyco – jest kompilatorem just-in-time (JIT) dla

Pythona, co przyśpiesza wykonywanie 2-100x
(typowo 4x) (

http://psyco.sourceforge.net

)

23

background image

SWIG

• SWIG jest generatorem interfejsów do kodu

C/C++ z języków skryptowych (Perl, Python,
Ruby, Tcl, …).

• Interfejsy są generowane na podstawie

deklaracji w kodzie C/C++ (np. pliku
nagłówkowego) lub pliku interfejsu

• Szczegóły na 690 stronach dokumentacji 

24

background image

SWIG – działanie

25

background image

SWIG – wykonanie

26

background image

SWIG – kod w C

/* File : example.c */
#include <time.h>
double My_variable = 3.0;

int fact(int n) {

if (n <= 1) return 1;

else return n*fact(n-1);

}

int my_mod(int x, int y) {

return (x%y);

}

char *get_time()
{

time_t ltime;

time(&ltime);

return ctime(&ltime);

}

http://www.swig.org/tutorial.html

27

background image

SWIG – plik interfejsu

/* 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();

28

background image

SWIG – kompilacja i uruchomienie

% swig -python example.i
% gcc -c example.c example_wrap.c \
-I/usr/local/include/python2.1
% ld -shared example.o example_wrap.o -o _example.so

% python
>>> import example
>>> example.fact(5)
120
>>> example.my_mod(7,3)
1
>>> example.get_time()
'Sun Feb 11 23:01:07 1996‘

29

background image

F2PY dla C – funkcja w C

/* File foo.c */
void foo(int n, double *x, double *y)
{
int i;
for (i=0;i<n;i++) {

y[i] = x[i] + i;

}
}

http://www.scipy.org/Cookbook/f2py_and_NumPy

30

background image

F2PY dla C – plik sygnatury

! File m.pyf
python module m
interface
subroutine foo(n,x,y)
intent(c) foo ! foo is a C function
intent(c) ! all foo arguments are
! considered as C based
integer intent(hide), depend(x) :: n=len(x) ! n is the length
! of input array x
double precision intent(in) :: x(n) ! x is input array
! (or arbitrary

sequence)

double precision intent(out) :: y(n) ! y is output array,
! see code in foo.c
end subroutine foo
end interface
end python module m

31

background image

F2PY dla C – plik setup.py

# File setup.py
def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import

Configuration

config =

Configuration('',parent_package,top_path)


config.add_extension('m',
sources =

['m.pyf','foo.c'])

return config
if __name__ == "__main__":
from numpy.distutils.core import setup
setup(**configuration(top_path='').todict())

32

background image

F2PY dla C – kompilacja

i uruchomienie

• Kompilacja w wyniku której powstaje moduł C (m.so/m.pyd) :


> f2py m.pyf foo.c -c

>>> import m
>>> print m.__doc__
This module 'm' is auto-generated with f2py (version:2_2130).
Functions:
y = foo(x)
.
>>> print m.foo.__doc__
foo - Function signature:
y = foo(x)
Required arguments:
x : input rank-1 array('d') with bounds (n)
Return objects:
y : rank-1 array('d') with bounds (n)
>>> print m.foo([1,2,3,4,5])
[ 1. 3. 5. 7. 9.]

33

background image

ctypes

• Moduł Pythona umożliwia bezpośrednie

wołanie funkcji w bibliotekach dynamicznych

• Zapewnia obsługę typów danych C oraz

konwencję wywołao.

• Dokumentacja:

– ctypes – A foreign function library for Python

(dokumentacja Pythona)

http://starship.python.net/crew/theller/ctypes/tu
torial.html

34

background image

ctypes – typy danych I

Typ ctypes

Typ C

Typ Python

c_char

char

1-character string

c_wchar

wchar_t

1-character unicode
string

c_byte

char

int/long

c_ubyte

unsigned char

int/long

c_short

short

int/long

c_ushort

unsigned short

int/long

c_int

int

int/long

c_uint

unsigned int

int/long

c_long

long

int/long

c_ulong

unsigned long

int/long

35

background image

ctypes – typy danych II

Typ ctypes

Typ C

Typ Python

c_longlong

__int64 or long long

int/long

c_ulonglong

unsigned __int64 or unsigned long long

int/long

c_float

float

float

c_double

double

float

c_longdouble

long double

float

c_char_p

char * (NUL terminated)

string or None

c_wchar_p

wchar_t * (NUL terminated)

unicode or None

c_void_p

void *

int/long or None

36

background image

ctypes – ładowanie biblioteki

# WINDOWS
>>> from ctypes import *
>>> print windll.kernel32
<WinDLL 'kernel32', handle ... at ...>
>>> print cdll.msvcrt
<CDLL 'msvcrt', handle ... at ...>
>>> libc = cdll.msvcrt

# LINUX
>>> cdll.LoadLibrary("libc.so.6")
<CDLL 'libc.so.6', handle ... at ...>
>>> libc = CDLL("libc.so.6")
>>> libc
<CDLL 'libc.so.6', handle ... at ...>

37

background image

ctypes – wywołanie funkcji

# EX1
from ctypes import *
libName = 'libc.so'

# on a UNIX-based system

libName = 'msvcrt.dll'

# on Windows

libc = CDLL(libName)
libc.printf("Hello, World!\n")

# EX2
from ctypes import c_int, WINFUNCTYPE, windll
from ctypes.wintypes import HWND, LPCSTR, UINT
prototype = WINFUNCTYPE(c_int, HWND, LPCSTR, LPCSTR, UINT)
paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1,

"caption", None), (1, "flags", 0)

MessageBox = prototype(("MessageBoxA", windll.user32),

paramflags)

38

background image

OSADZANIE PYTHONA

39

background image

Osadzanie – template

#include <Python.h>

int main(int argc, char **argv)
{
Py_Initialize();
PyRun_SimpleString("print('Hello!')");
Py_Finalize();
return 0;
}

40

background image

Osadzanie – funkcje

• Wykonanie z łaocucha znaków:

Py_Initialize();
PyRun_SimpleString("i = 2");
PyRun_SimpleString("i = i*innprint i");
Py_Finalize();

• Wykonanie z pliku:

Py_Initialize();
FILE * f = fopen("test.py", "r");
PyRun_SimpleFile(f, "test.py");
Py_Finalize();

41

background image

Dostęp do Pythona z C

• Importowanie modułów Pythona (emulacja

polecenia import)

• Dostęp do obiektów zdefiniowanych w modułach
• Wywoływanie funkcji Python (funkcje w klasach,

modułach)

• Dostęp do zmiennych/atrybutów obiektów
• Konwersja typów Python/C
• Zarządzanie pamięcią

42

background image

Wywołanie funkcji w module

PyObject *pName, *pModule, *pArgs, *pFunc, *pValue;

# Import modułu Python
Py_Initialize();
pName = PyString_FromString("mymod");
pModule = PyImport_Import(pName);

# Pobranie funkcji z modułu
pFunc = PyObject_GetAttrString(pModule, "foo");

# Wywołanie funkcji
pValue = PyObject_CallObject(pFunc, pArgs);

43


Wyszukiwarka

Podobne podstrony:
Python dla naukowca 03
ocena ryzyka dla naukowych
Python dla profesjonalistow Debugowanie testowanie i utrzymywanie kodu pytpro
Black Hat Python Jezyk Python dla hakerow i pentesterow
Black Hat Python Jezyk Python dla hakerow i pentesterow blahap
Stypendia na pobyty badawcze dla naukowcow i nauczycieli akademickich
Black Hat Python Jezyk Python dla hakerow i pentesterow blahap
Black Hat Python Jezyk Python dla hakerow i pentesterow
Black Hat Python Jezyk Python dla hakerow i pentesterow blahap
6 - spr pochodne i calki (2) dla ZSZ-PF34 - pl 4[1], Pomoce naukowe SGSP, Moje Dokumenty, Matematyka
Udogodnienia dla osób niepe, informacja naukowa i bibliotekoznawstwo 3 semestr
Egzaminacyjne pytania testowe z medycyny rodzinnej dla samokształcenia i samoocen2, Pomoce naukowe,

więcej podobnych podstron