[Commits] python.it commit r157 - python/contrib/faq/trunk
commit a svn.python.it
commit a svn.python.it
Mer 24 Maggio 2006 23:52:32 CEST
Author: meo
Date: Wed May 24 23:52:28 2006
New Revision: 157
Modified:
python/contrib/faq/trunk/extending.ht
Log:
Revisione finale
Modified: python/contrib/faq/trunk/extending.ht
==============================================================================
--- python/contrib/faq/trunk/extending.ht (original)
+++ python/contrib/faq/trunk/extending.ht Wed May 24 23:52:28 2006
@@ -1,522 +1,523 @@
-Title: FAQ Estendere/Includere Python
-Content-type: text/x-rst
-
-====================================
-FAQ Estendere/Includere Python
-====================================
-
-:Date: $Date: 2004-04-08 17:05:47 +0200 (gio, 08 apr 2004) $
-:Version: $Revision: 7294 $
-:Web site: http://www.python.org/
-:Traduzione: Bartolomeo Bogliolo 1 Aprile 2006
-
-.. contents::
-.. sectnum::
-
-
-**Traduzione Italiana**
-
-Questo documento, di pubblico dominio, e' stato tradotto da
-`Meo Bogliolo <mailto:meo a bogliolo.name?subject=Traduzione Embedding FAQ>`_
-(revisionato da
-`Daniele Tricoli <mailto:eriol a huine.org?subject=Traduzione Embedding FAQ>`_
-): potete contattarli per qualsiasi
-commento o correzione.
-
-
-Si possono creare proprie funzioni in C?
-------------------------------------------
-Si, e' possibile creare moduli built-in che contengono funzioni,
-variabili, eccezioni ed anche nuovi tipi in C. Tutto cio' e' spiegato
-nel documento "Extending and Embedding the Python Interpreter" (http://docs.python.org/ext/ext.html).
-
-Anche la maggior parte dei libri di livello intermedio o avanzato
-su Python trattano l'argomento.
-
-
-Si possono creare proprie funzioni in C++?
---------------------------------------------
-Si, utilizzando le caratteristiche di compatibilita' al C tipiche del C++.
-Si deve porre ``extern "C" { ... }`` a delimitare gli include file di Python
-e porre ``extern "C"`` prima di ogni funzione che debba essere chiamata
-dall'interprete Python.
-Oggetti C++ globali o statici con costruttori non sono
-adatti per tale utilizzo.
-
-
-Scrivere in C e' difficile; ci sono altre possibilita'?
---------------------------------------------------------
-Vi sono una serie di alternative a scrivere estensioni in C,
-dipende da cosa si cerca di fare.
-
-Se e' necessaria una maggior velocita' di esecuzione
-`Psyco <http://psyco.sourceforge.net/>`_
-genera codice assembler x86
-dal bytecode Python. E' possibile utilizzare Psyco per compilare le
-funzioni piu' critiche del codice ed ottenere un notevole incremento
-di prestazioni con uno sforzo molto limitato, naturalmente se si
-utilizza un sistema con un processore compatibile a x86.
-
-`Pyrex <http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/>`_
-e' un compilatore che accetta una sintassi leggermente modifica di Python
-e genera il corrispondente codice C. Pyrex consente di scrivere
-un'estensione senza dover imparare le API C di Python.
-
-Se debbono essere interfacciate librerie C per cui non esista ancora
-un'estensione per Python e' si puo' provare ad effettuare un wrapping
-delle funzioni e dei tipi di dati con
-`SWIG <http://www.swig.org>`_.
-Per le librerie C++ si possono utilizzare
-`SIP <http://www.riverbankcomputing.co.uk/sip/>`_,
-`CXX <http://cxx.sourceforge.net/>`_,
-`Boost <http://www.boost.org/libs/python/doc/index.html>`_
-o `Weave <http://www.scipy.org/site_content/weave>`_.
-
-
-Come si possono eseguire comandi Python dal C?
-------------------------------------------------------------
-La funzione piu' ad alto livello e'
-``PyRun_SimpleString()``
-che riceve come argomento una singola stringa che deve essere
-eseguita nel contesto del modulo
-``__main__`` e restituisce 0 in caso di successo e -1
-quando occorre un'eccezione (compreso ``SyntaxError``).
-Se e' necessario un maggior controllo deve essere utilizzato
-``PyRun_String()``;
-si veda il sorgente di ``PyRun_SimpleString()`` in Python/pythonrun.c.
-
-
-Si puo' calcolare il valore di un'espressione Python dal C?
-----------------------------------------------------------------
-Richiamando la funzione ``PyRun_String()``, citata nella domanda
-precedente, con il simbolo di partenza
-``Py_eval_input``; essa
-parsifica un espressione, la valuta e restituisce il suo valore.
-
-
-Come si estraggono i valori in C da un oggetto Python?
-------------------------------------------------------
-Dipende dal tipo d'oggetto. Se e' una tupla
-``PyTupleSize(o)`` restituisce la sua lunghezza e ``PyTuple_GetItem(o, i)``
-restituisce il suo i-esimo elemento.
-Le liste hanno funzioni simili: ``PyListSize(o)``
-e ``PyList_GetItem(o, i)``.
-
-Per le stringhe ``PyString_Size(o)`` restituisce
-la sua lunghezza e ``PyString_AsString(o)`` un puntatore al suo valore.
-Si noti che le stringhe in Python possono contenere byte a null e quindi
-la funzione C ``strlen()``
-non deve essere utilizzata.
-
-Per controllare il tipo di un oggetto innanzi tutto bisogna assicurarsi
-che non sia NULL e quindi utilizzare
-``PyString_Check(o)``, ``PyTuple_Check(o)``,
-``PyList_Check(o)``, ecc.
-
-E' anche disponibile un'API di alto livello agli oggetti Python
-che e' fornita dall'interfaccia chiamata 'astratta' -- si legga
-``Include/abstract.h`` per maggiori dettagli. Permette di
-interfacciarsi con ogni tipo di sequenza Python utilizzando
-chiamate come
-``PySequence_Length()``, ``PySequence_GetItem()``, ecc.)
-cosi' come altri utili protocolli.
-
-
-Come si puo' richiamare Py_BuildValue() per creare una tupla di lunghezza arbitraria?
----------------------------------------------------------------------------------------
-Non e' possibile.
-E' necessario richiamare
-``t = PyTuple_New(n)`` e caricarla con gli oggetti
-utilizzando ``PyTuple_SetItem(t, i, o)`` -- si deve notare che questa
-tecnica "consuma"
-un contatore di riferimento ad ``o``, quindi e' necessario richiamare ``Py_INCREF``.
-Le liste hanno funzioni similari come ``PyList_New(n)`` e
-``PyList_SetItem(l, i, o)``.
-Si noti che si *deve* impostare un valore a tutti gli elementi di una
-tupla prima di passare la tupla all'interprete Python --
-``PyTuple_New(n)`` inizializza i valori a NULL, che non e' un valore
-valido per Python.
-
-
-Come si puo' richiamare un metodo di un oggetto in C?
-------------------------------------------------------
-La funzione ``PyObject_CallMethod()`` puo' essere utilizzata per richiamare
-un qualsiasi metodo di un oggetto.
-I parametri sono l'oggetto, il nome del metodo da richiamare,
-una stringa di formato come quella utilizzata con
-``Py_BuildValue()`` ed il valore degli argomenti::
-
- PyObject *
- PyObject_CallMethod(PyObject *object, char *method_name,
- char *arg_format, ...);
-
-Questo funziona per ogni oggetto che abbia metodi -- sia che siano
-built-in che definiti dall'utente. Il programmatore ha la responsabilita'
-di lanciare ``Py_DECREF`` sul valore di ritorno.
-
-Ad esempio per richiamare il metodo "seek" su un oggetto file con
-argomenti 10, 0 ("f" e' il puntatore all'oggetto file)::
-
- res = PyObject_CallMethod(f, "seek", "(ii)", 10, 0);
- if (res == NULL) {
- ... an exception occurred ...
- }
- else {
- Py_DECREF(res);
- }
-
-Poiche' ``PyObject_CallObject()`` richiede *sempre* una tupla come
-lista di argomenti, per richiamare una funzione senza argomenti deve
-essere passato "()" come formato e per chiamare una funzione con un
-argomento questo va posto tra parentesi: "(i)".
-
-
-Come si puo' raccogliere l'output da PyErr_Print() (o da qualunque cosa che scriva su standard output/error)?
---------------------------------------------------------------------------------------------------------------
-Nel codice Python si deve definire un oggetto che supporti il metodo
-``write()``.
-Quindi va assegnato questo oggetto a ``sys.stdout`` e ``sys.stderr``.
-Ora chiamando print_error o lasciando operare il meccanismo di traceback
-standard l'output sara' ridiretto ovunque il metodo ``write()`` lo invia.
-
-Il modo piu' semplice di farlo e' utilizzare la classe StringIO della
-libreria standard.
-
-Codice d'esempio per catturare stdout::
-
- >>> class StdoutCatcher:
- ... def __init__(self):
- ... self.data = ''
- ... def write(self, stuff):
- ... self.data = self.data + stuff
- ...
- >>> import sys
- >>> sys.stdout = StdoutCatcher()
- >>> print 'foo'
- >>> print 'hello world!'
- >>> sys.stderr.write(sys.stdout.data)
- foo
- hello world!
-
-
-Come si accede ad un modulo Python dal C?
----------------------------------------------------------
-Per ottenere un puntatore al modulo dell'oggetto si utilizza::
-
- module = PyImport_ImportModule("<modulename>");
-
-Se il modulo non e' ancora stato importato (ovvero non e' ancora presente in
-``sys.modules``), questo viene inizializzato; altrimenti
-restituisce semplicemente
-il valore di ``sys.modules["<modulename>"]``.
-Deve essere notato che questo non inserisce
-il modulo in alcun namespace -- assicura solamente che il modulo sia
-inizializzato e caricato in ``sys.modules``.
-
-A questo punto e' possibile accedere agli attributi del modulo
-(ogni nome definito nel modulo) come segue:
-
- attr = PyObject_GetAttrString(module, "<attrname>");
-
-Chiamando ``PyObject_SetAttrString()``
-si possono anche assegnare valori alle variabili del modulo.
-
-
-Come si interfaccia un oggetto C++ da Python?
-------------------------------------------------------
-A seconda delle necessita' vi sono differenti soluzioni. Per farlo
-manualmente si consiglia di iniziare a leggere
-`il documento "Extending and Embedding" <http://docs.python.org/ext/ext.html>`_.
-Per quello che riguarda il run-time di Python non c'e' una grande
-differenza tra il C ed il C++ -- percio' la strategia di costruire un
-nuovo tipo Python
-intorno ad un tipo struttura C (puntatore) funziona anche con i gli
-oggetti C++.
-
-Per le librerie C++ si possono utilizzare
-`SIP <http://www.riverbankcomputing.co.uk/sip/>`_,
-`CXX <http://cxx.sourceforge.net/>`_,
-`Boost <http://www.boost.org/libs/python/doc/index.html>`_,
-o `Weave <http://www.scipy.org/site_content/weave>`_.
-`SWIG <http://www.swig.org>`_
-e' un tool automatico simile che supporta solo librerie C.
-
-
-Aggiungendo un modulo nel file di Setup il make fallisce. Perche'?
-----------------------------------------------------------------------
-Il Setup deve finire con un carattere di fine riga, se non e' presente
-la costruzione fallisce. (Risolvere questo problema richiederebbe un
-noioso shell script,
-ed il bug e' cosi' poco importante che non ne vale la pena.)
-
-
-Come si effettua il debug di un'estensione?
---------------------------------------------
-Utilizzando il GDB con estensioni caricate dinamicamente, non e' possibile
-impostare un breakpoint nell'estensione fino a che non e' caricata.
-
-Basta aggiungere nel file ``.gdbinit`` (o eseguire interattivamente),
-il comando::
-
- br _PyImport_LoadDynamicModule
-
-Quindi, eseguendo GDB::
-
- $ gdb /local/bin/python
- gdb) run myscript.py
- gdb) continue # repeat until your extension is loaded
- gdb) finish # so that your extension is loaded
- gdb) br myfunction.c:50
- gdb) continue
-
-
-Cercando di compilare un modulo Python su un sistema Linux risultano mancanti alcuni file. Perche'?
---------------------------------------------------------------------------------------------------
-La maggior parte delle versioni a pacchetto di Python non include la
-directory /usr/lib/python2.x/config/ che contiene alcuni file necessari
-per compilare le estensioni Python.
-
-Per Red Hat e' necessario installare l'RPM python-devel.
-
-Per Debian, e' necessario lanciare il comando ``apt-get install python-dev``.
-
-
-Cosa significa "SystemError: _PyImport_FixupExtension: module nomemodulo not loaded"?
--------------------------------------------------------------------------------------------------------
-Significa che e' stata creato un modulo d'estensione chiamato "nomemodulo",
-ma la funzione di init non si inizializza con quel nome.
-
-Ogni funzione di init di un modulo deve avere una linea simile a::
-
- module = Py_InitModule("nomemodulo", nomemodulo_functions);
-
-Se la stringa passata a questa funzione non ha lo stesso nome del
-modulo d'estensione viene sollevata l'eccezione ``SystemError``.
-
-
-Come e' possibile restituire "incomplete input" a fronte di un "invalid input"?
---------------------------------------------------------------------------------
-A volte si vuole emulare il comportamento dell'interprete interattivo di Python
-che restituisce un prompt di continuazione quando l'input non e'
-completo (e.g. e' stato digitato l'inizio di una istruzione di "if",
-non e' stata chiusa una parentesi o gli apici tripli di stringa)
-ma restituisce un errore di sintassi immediatamente quando l'input
-non e' corretto.
-
-In Python si puo' utilizzare il modulo ``codeop``, che approssima il
-comportamento del parser a sufficienza. Ad esempio lo utilizza IDLE.
-
-Il modo piu' facile per farlo in C e' richiamare ``PyRun_InteractiveLoop()``
-(magari in un thread separato) e lasciare che sia l'interprete Python
-a gestire l'input. E' anche possibile far puntare ``PyOS_ReadlineFunctionPointer``
-ad una routine custom di gestione dell'input. Si vedano ``Modules/readline.c`` e
-``Parser/myreadline.c`` per ulteriori indicazioni.
-
-Tuttavia a volte si deve eseguire l'interprete Python nello
-stesso thread dell'applicazione e non e' possibile far interrompere
-the same thread as your rest application and you can't allow the
-``PyRun_InteractiveLoop()`` in attesa di un input dell'utente.
-L'unica soluzione e' chiamare ``PyParser_ParseString()`` e controllare quando
-``e.error`` e' uguale a ``E_EOF`` (che indica che l'input non e' completo).
-Ecco un frammento di codice d'esempio, non testato, ispirato ad un programma di
-Alex Farber::
-
- #include <Python.h>
- #include <node.h>
- #include <errcode.h>
- #include <grammar.h>
- #include <parsetok.h>
- #include <compile.h>
-
- int testcomplete(char *code)
- /* code should end in \n */
- /* return -1 for error, 0 for incomplete, 1 for complete */
- {
- node *n;
- perrdetail e;
-
- n = PyParser_ParseString(code, &_PyParser_Grammar,
- Py_file_input, &e);
- if (n == NULL) {
- if (e.error == E_EOF)
- return 0;
- return -1;
- }
-
- PyNode_Free(n);
- return 1;
- }
-
-Un'altra soluzione e' di compilare la stringa ricevuta con
-``Py_CompileString()``. Se si compila senza errori si puo' provare ad eseguire il
-codice chiamando ``PyEval_EvalCode()``. Altrimenti si salva l'input per dopo.
-Se la compilazione fallisce si deve cercare se si tratta di un errore o se
-e' richiesto altro input estraendo il messaggio dalla tupla dell'eccezione
-e confrontandola con la stringa "unexpected EOF while parsing".
-Ecco un esempio completo che utilizza la libreria GNU readline
-(si puo' ignorare SIGINT nel richiamare readline())::
-
- #include <stdio.h>
- #include <readline.h>
-
- #include <Python.h>
- #include <object.h>
- #include <compile.h>
- #include <eval.h>
-
- int main (int argc, char* argv[])
- {
- int i, j, done = 0; /* lengths of line, code */
- char ps1[] = ">>> ";
- char ps2[] = "... ";
- char *prompt = ps1;
- char *msg, *line, *code = NULL;
- PyObject *src, *glb, *loc;
- PyObject *exc, *val, *trb, *obj, *dum;
-
- Py_Initialize ();
- loc = PyDict_New ();
- glb = PyDict_New ();
- PyDict_SetItemString (glb, "__builtins__", PyEval_GetBuiltins ());
-
- while (!done)
- {
- line = readline (prompt);
-
- if (NULL == line) /* CTRL-D pressed */
- {
- done = 1;
- }
- else
- {
- i = strlen (line);
-
- if (i > 0)
- add_history (line); /* save non-empty lines */
-
- if (NULL == code) /* nothing in code yet */
- j = 0;
- else
- j = strlen (code);
-
- code = realloc (code, i + j + 2);
- if (NULL == code) /* out of memory */
- exit (1);
-
- if (0 == j) /* code was empty, so */
- code[0] = '\0'; /* keep strncat happy */
-
- strncat (code, line, i); /* append line to code */
- code[i + j] = '\n'; /* append '\n' to code */
- code[i + j + 1] = '\0';
-
- src = Py_CompileString (code, "<stdin>", Py_single_input);
-
- if (NULL != src) /* compiled just fine - */
- {
- if (ps1 == prompt || /* ">>> " or */
- '\n' == code[i + j - 1]) /* "... " and double '\n' */
- { /* so execute it */
- dum = PyEval_EvalCode ((PyCodeObject *)src, glb, loc);
- Py_XDECREF (dum);
- Py_XDECREF (src);
- free (code);
- code = NULL;
- if (PyErr_Occurred ())
- PyErr_Print ();
- prompt = ps1;
- }
- } /* syntax error or E_EOF? */
- else if (PyErr_ExceptionMatches (PyExc_SyntaxError))
- {
- PyErr_Fetch (&exc, &val, &trb); /* clears exception! */
-
- if (PyArg_ParseTuple (val, "sO", &msg, &obj) &&
- !strcmp (msg, "unexpected EOF while parsing")) /* E_EOF */
- {
- Py_XDECREF (exc);
- Py_XDECREF (val);
- Py_XDECREF (trb);
- prompt = ps2;
- }
- else /* some other syntax error */
- {
- PyErr_Restore (exc, val, trb);
- PyErr_Print ();
- free (code);
- code = NULL;
- prompt = ps1;
- }
- }
- else /* some non-syntax error */
- {
- PyErr_Print ();
- free (code);
- code = NULL;
- prompt = ps1;
- }
-
- free (line);
- }
- }
-
- Py_XDECREF(glb);
- Py_XDECREF(loc);
- Py_Finalize();
- exit(0);
- }
-
-
-
-Come si cercano simboli g++ non definiti __builtin_new o __pure_virtual?
------------------------------------------------------------------------------------
-Per caricare i moduli di estensione g++ bisogna ricompilare Python, relinkarlo
-utilizzando g++ (cambiando LINKCC nel Makefile dei Moludi Python) e
-linkare i moduli d'estensione utilizzando il g++
-(e.g., "g++ -shared -o mymodule.so mymodule.o").
-
-
-Si possono creare classi di oggetti con metodi implementati in C ed altri in Python (eg. mediante ereditarieta')?
------------------------------------------------------------------------------------------------------------------------------------------------------
-A partire da Python 2.2, si puo' ereditare dalle classi builtin come int, list, dict, ecc.
-
-La Boost Python Library (BPL, http://www.boost.org/libs/python/doc/index.html)
-fornisce un modo per farlo dal C++ (ad esempio e' possibile ereditare da una
-classe d'estensione scritta in C++ utilizzando il BPL).
-
-
-Perche' importando un modulo si verifica l'errore "undefined symbol: PyUnicodeUCS2*"?
---------------------------------------------------------------------------------------------------
-Poiche' si sta utilizzando una versione di Python che utilizza
-una rappresentazione a 4 byte
-dei caratteri Unicode mentre si sta importando un modulo che e' stato compilato
-con un Python che utilizza una rappresentazione a 2 byte (che e' il default).
-
-Se il nome del simbolo non definito che inizia con
-``PyUnicodeUCS4``, il problema e' l'opposto: Python utilizza caratteri
-Unicode a 2 byte ed il modulo d'estensione e' stato compilato con
-un Python che utilizza caratteri Unicode a 4 byte.
-
-Questo problema si verifica spesso utilizzando pacchetti d'estensione
-precostruiti. RedHat
-Linux 7.x, in particolare forniva un binario "python2" compilato con
-Unicode a 4 byte. Questo causa problemi di link solo se l'estensione
-utilizza una qualsiasi funzione ``PyUnicode_*()``. E' anche un problema
-se l'estensione utilizza una qualsiasi specifica di formato relativa
-agli Unicode per
-``Py_BuildValue`` (o simili) oppure una specifica di parametri per
-``PyArg_ParseTuple()``.
-
-E' possibile verificare la dimensione di un carattere Unicode sull'interprete
-Python controllando il valore di sys.maxunicode::
-
- >>> import sys
- >>> if sys.maxunicode > 65535:
- ... print 'UCS4 build'
- ... else:
- ... print 'UCS2 build'
-
-L'unico modo per risolvere il problema e' di utilizzare moduli
-d'estensione compilati con un binario Python che utilizzi la stessa dimensione
-per i caratteri Unicode.
-
+Title: FAQ Estendere/Includere Python
+Content-type: text/x-rst
+
+====================================
+FAQ Estendere/Includere Python
+====================================
+
+:Date: $Date: 2004-04-08 17:05:47 +0200 (gio, 08 apr 2004) $
+:Version: $Revision: 7294 $
+:Web site: http://www.python.org/
+:Traduzione: Bartolomeo Bogliolo 1 Aprile 2006
+
+.. contents::
+.. sectnum::
+
+
+**Traduzione Italiana**
+
+Questo documento, di pubblico dominio, e' stato tradotto da
+`Meo Bogliolo <mailto:meo a bogliolo.name?subject=Traduzione Embedding FAQ>`_
+(revisionato da
+`Daniele Tricoli <mailto:eriol a huine.org?subject=Traduzione Embedding FAQ>`_
+): potete contattarli per qualsiasi
+commento o correzione.
+
+
+Si possono creare proprie funzioni in C?
+------------------------------------------
+Si, e' possibile creare moduli built-in che contengono funzioni,
+variabili, eccezioni ed anche nuovi tipi in C. Tutto cio' e' spiegato
+nel documento "Extending and Embedding the Python Interpreter" (http://docs.python.org/ext/ext.html).
+
+Anche la maggior parte dei libri di livello intermedio o avanzato
+su Python trattano l'argomento.
+
+
+Si possono creare proprie funzioni in C++?
+--------------------------------------------
+Si, utilizzando le caratteristiche di compatibilita' al C tipiche del C++.
+Si deve porre ``extern "C" { ... }`` a delimitare gli include file di Python
+e porre ``extern "C"`` prima di ogni funzione che debba essere chiamata
+dall'interprete Python.
+Oggetti C++ globali o statici con costruttori non sono
+adatti per tale utilizzo.
+
+
+Scrivere in C e' difficile; ci sono altre possibilita'?
+--------------------------------------------------------
+Vi sono una serie di alternative a scrivere estensioni in C,
+dipende da cosa si cerca di fare.
+
+Se e' necessaria una maggior velocita' di esecuzione
+`Psyco <http://psyco.sourceforge.net/>`_
+genera codice assembler x86
+dal bytecode Python. E' possibile utilizzare Psyco per compilare le
+funzioni piu' critiche del codice ed ottenere un notevole incremento
+di prestazioni con uno sforzo molto limitato, naturalmente se si
+utilizza un sistema con un processore x86.
+
+`Pyrex <http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/>`_
+e' un compilatore che accetta una sintassi leggermente modificata di Python
+e genera il corrispondente codice C. Pyrex consente di scrivere
+un'estensione senza dover imparare le API C di Python.
+
+Se debbono essere interfacciate librerie C per cui non esista ancora
+un'estensione per Python si puo' effettuare un wrapping
+delle funzioni e dei tipi di dati con
+`SWIG <http://www.swig.org>`_.
+Per le librerie C++ si possono utilizzare
+`SIP <http://www.riverbankcomputing.co.uk/sip/>`_,
+`CXX <http://cxx.sourceforge.net/>`_,
+`Boost <http://www.boost.org/libs/python/doc/index.html>`_
+o `Weave <http://www.scipy.org/site_content/weave>`_.
+
+
+Come si possono eseguire comandi Python dal C?
+------------------------------------------------------------
+La funzione piu' ad alto livello e'
+``PyRun_SimpleString()``
+che riceve come argomento una singola stringa che deve essere
+eseguita nel contesto del modulo
+``__main__`` e restituisce 0 in caso di successo e -1
+quando occorre un'eccezione (compreso ``SyntaxError``).
+Se e' necessario un maggior controllo deve essere utilizzata
+``PyRun_String()``;
+si veda il sorgente di ``PyRun_SimpleString()`` in Python/pythonrun.c.
+
+
+Si puo' calcolare il valore di un'espressione Python dal C?
+----------------------------------------------------------------
+Richiamando la funzione ``PyRun_String()``, citata nella domanda
+precedente, con il simbolo di partenza
+``Py_eval_input``; essa
+parsifica un espressione, la valuta e restituisce il suo valore.
+
+
+Come si estraggono i valori in C da un oggetto Python?
+------------------------------------------------------
+Dipende dal tipo d'oggetto. Se e' una tupla
+``PyTupleSize(o)`` restituisce la sua lunghezza e ``PyTuple_GetItem(o, i)``
+restituisce il suo i-esimo elemento.
+Le liste hanno funzioni simili: ``PyListSize(o)``
+e ``PyList_GetItem(o, i)``.
+
+Per le stringhe ``PyString_Size(o)`` restituisce
+la sua lunghezza e ``PyString_AsString(o)`` un puntatore al suo valore.
+Si noti che le stringhe in Python possono contenere byte a null e quindi
+la funzione C ``strlen()``
+non deve essere utilizzata.
+
+Per controllare il tipo di un oggetto innanzi tutto bisogna assicurarsi
+che non sia NULL e quindi utilizzare
+``PyString_Check(o)``, ``PyTuple_Check(o)``,
+``PyList_Check(o)``, ecc.
+
+E' anche disponibile un'API di alto livello agli oggetti Python
+che e' fornita dall'interfaccia chiamata 'astratta' -- si legga
+``Include/abstract.h`` per maggiori dettagli. Permette di
+interfacciarsi con ogni tipo di sequenza Python utilizzando
+chiamate come
+``PySequence_Length()``, ``PySequence_GetItem()``, ecc.)
+cosi' come altri utili protocolli.
+
+
+Come si puo' richiamare Py_BuildValue() per creare una tupla di lunghezza arbitraria?
+---------------------------------------------------------------------------------------
+Non e' possibile.
+E' necessario richiamare
+``t = PyTuple_New(n)`` e caricarla con gli oggetti
+utilizzando ``PyTuple_SetItem(t, i, o)`` -- si deve notare che questa
+tecnica "consuma"
+un contatore di riferimento ad ``o``, quindi e' necessario richiamare ``Py_INCREF``.
+Le liste hanno funzioni similari come ``PyList_New(n)`` e
+``PyList_SetItem(l, i, o)``.
+Si noti che si *deve* impostare un valore a tutti gli elementi di una
+tupla prima di passare la tupla all'interprete Python --
+``PyTuple_New(n)`` inizializza i valori a NULL, che non e' un valore
+valido per Python.
+
+
+Come si puo' richiamare un metodo di un oggetto in C?
+------------------------------------------------------
+La funzione ``PyObject_CallMethod()`` puo' essere utilizzata per richiamare
+un qualsiasi metodo di un oggetto.
+I parametri sono l'oggetto, il nome del metodo da richiamare,
+una stringa di formato come quella utilizzata con
+``Py_BuildValue()`` ed il valore degli argomenti::
+
+ PyObject *
+ PyObject_CallMethod(PyObject *object, char *method_name,
+ char *arg_format, ...);
+
+Questo funziona per ogni oggetto che abbia metodi -- sia che siano
+built-in che definiti dall'utente. Il programmatore ha la responsabilita'
+di lanciare ``Py_DECREF`` sul valore di ritorno.
+
+Ad esempio per richiamare il metodo "seek" su un oggetto file con
+argomenti 10, 0 ("f" e' il puntatore all'oggetto file)::
+
+ res = PyObject_CallMethod(f, "seek", "(ii)", 10, 0);
+ if (res == NULL) {
+ ... an exception occurred ...
+ }
+ else {
+ Py_DECREF(res);
+ }
+
+Poiche' ``PyObject_CallObject()`` richiede *sempre* una tupla come
+lista di argomenti, per richiamare una funzione senza argomenti deve
+essere passato "()" come formato e per chiamare una funzione con un
+argomento questo va posto tra parentesi: "(i)".
+
+
+Come si puo' raccogliere l'output da PyErr_Print() (o da qualunque cosa che scriva su standard output/error)?
+--------------------------------------------------------------------------------------------------------------
+Nel codice Python si deve definire un oggetto che supporti il metodo
+``write()``.
+Quindi va assegnato questo oggetto a ``sys.stdout`` e ``sys.stderr``.
+Ora chiamando print_error o lasciando operare il meccanismo di traceback
+standard l'output sara' ridiretto ovunque il metodo ``write()`` lo invia.
+
+Il modo piu' semplice di farlo e' utilizzare la classe StringIO della
+libreria standard.
+
+Codice d'esempio per catturare stdout::
+
+ >>> class StdoutCatcher:
+ ... def __init__(self):
+ ... self.data = ''
+ ... def write(self, stuff):
+ ... self.data = self.data + stuff
+ ...
+ >>> import sys
+ >>> sys.stdout = StdoutCatcher()
+ >>> print 'foo'
+ >>> print 'hello world!'
+ >>> sys.stderr.write(sys.stdout.data)
+ foo
+ hello world!
+
+
+Come si accede ad un modulo Python dal C?
+---------------------------------------------------------
+Per ottenere un puntatore al modulo si utilizza::
+
+ module = PyImport_ImportModule("<modulename>");
+
+Se il modulo non e' ancora stato importato (ovvero non e' ancora presente in
+``sys.modules``), questo viene inizializzato; altrimenti
+restituisce semplicemente
+il valore di ``sys.modules["<modulename>"]``.
+Deve essere notato che questo non inserisce
+il modulo in alcun namespace -- assicura solamente che il modulo sia
+inizializzato e caricato in ``sys.modules``.
+
+A questo punto e' possibile accedere agli attributi del modulo
+(ogni nome definito nel modulo) come segue:
+
+ attr = PyObject_GetAttrString(module, "<attrname>");
+
+Chiamando ``PyObject_SetAttrString()``
+si possono anche assegnare valori alle variabili del modulo.
+
+
+Come si interfaccia un oggetto C++ da Python?
+------------------------------------------------------
+A seconda delle necessita' vi sono differenti soluzioni. Per farlo
+manualmente si consiglia di iniziare a leggere
+`il documento "Extending and Embedding" <http://docs.python.org/ext/ext.html>`_.
+Per quello che riguarda il run-time di Python non c'e' una grande
+differenza tra il C ed il C++ -- percio' la strategia di costruire un
+nuovo tipo Python
+intorno ad una struttura C (puntatore) funziona anche con gli
+oggetti C++.
+
+Per le librerie C++ si possono utilizzare
+`SIP <http://www.riverbankcomputing.co.uk/sip/>`_,
+`CXX <http://cxx.sourceforge.net/>`_,
+`Boost <http://www.boost.org/libs/python/doc/index.html>`_,
+o `Weave <http://www.scipy.org/site_content/weave>`_.
+`SWIG <http://www.swig.org>`_
+e' un tool automatico simile che supporta solo librerie C.
+
+
+Aggiungendo un modulo nel file di Setup il make fallisce. Perche'?
+----------------------------------------------------------------------
+Il Setup deve finire con un carattere di fine riga, se non e' presente
+la costruzione fallisce. (Risolvere questo problema richiederebbe un
+noioso shell script,
+ed il bug e' cosi' poco importante che non ne vale la pena.)
+
+
+Come si effettua il debug di un'estensione?
+--------------------------------------------
+Utilizzando il GDB con estensioni caricate dinamicamente, non e' possibile
+impostare un breakpoint nell'estensione fino a che non e' caricata.
+
+Basta aggiungere nel file ``.gdbinit`` (o eseguire interattivamente),
+il comando::
+
+ br _PyImport_LoadDynamicModule
+
+Quindi, eseguendo GDB::
+
+ $ gdb /local/bin/python
+ gdb) run myscript.py
+ gdb) continue # repeat until your extension is loaded
+ gdb) finish # so that your extension is loaded
+ gdb) br myfunction.c:50
+ gdb) continue
+
+
+Cercando di compilare un modulo Python su un sistema Linux risultano mancanti alcuni file. Perche'?
+--------------------------------------------------------------------------------------------------
+La maggior parte delle versioni pacchettizzate di Python non include la
+directory /usr/lib/python2.x/config/ che contiene alcuni file necessari
+per compilare le estensioni Python.
+
+Per Red Hat e' necessario installare l'RPM python-devel.
+
+Per Debian, e' necessario lanciare il comando ``apt-get install python-dev``.
+
+
+Cosa significa "SystemError: _PyImport_FixupExtension: module nomemodulo not loaded"?
+-------------------------------------------------------------------------------------------------------
+Significa che e' stata creato un modulo d'estensione chiamato "nomemodulo",
+ma la funzione di init non lo inizializza con quel nome.
+
+Ogni funzione di init di un modulo deve avere una linea simile a::
+
+ module = Py_InitModule("nomemodulo", nomemodulo_functions);
+
+Se la stringa passata a questa funzione non ha lo stesso nome del
+modulo d'estensione viene sollevata l'eccezione ``SystemError``.
+
+
+Come e' possibile restituire "incomplete input" a fronte di un "invalid input"?
+--------------------------------------------------------------------------------
+A volte si vuole emulare il comportamento dell'interprete interattivo di Python
+che restituisce un prompt di continuazione quando l'input non e'
+completo (e.g. e' stato digitato l'inizio di una istruzione di "if",
+non e' stata chiusa una parentesi o gli apici tripli di stringa)
+ma restituisce un errore di sintassi immediatamente quando l'input
+non e' corretto.
+
+In Python si puo' utilizzare il modulo ``codeop``, che approssima il
+comportamento del parser a sufficienza. Ad esempio lo utilizza IDLE.
+
+Il modo piu' facile per farlo in C e' richiamare ``PyRun_InteractiveLoop()``
+(magari in un thread separato) e lasciare che sia l'interprete Python
+a gestire l'input. E' anche possibile far puntare ``PyOS_ReadlineFunctionPointer``
+ad una routine custom di gestione dell'input. Si vedano ``Modules/readline.c`` e
+``Parser/myreadline.c`` per ulteriori indicazioni.
+
+Tuttavia a volte si deve eseguire l'interprete Python nello
+stesso thread dell'applicazione e non e' possibile far
+interrompere
+``PyRun_InteractiveLoop()`` in attesa di un input dell'utente.
+L'unica soluzione e' chiamare ``PyParser_ParseString()`` e controllare quando
+``e.error`` e' uguale a ``E_EOF`` (che indica che l'input non e' completo).
+Ecco un frammento di codice d'esempio, non testato, ispirato ad un programma di
+Alex Farber::
+
+ #include <Python.h>
+ #include <node.h>
+ #include <errcode.h>
+ #include <grammar.h>
+ #include <parsetok.h>
+ #include <compile.h>
+
+ int testcomplete(char *code)
+ /* code should end in \n */
+ /* return -1 for error, 0 for incomplete, 1 for complete */
+ {
+ node *n;
+ perrdetail e;
+
+ n = PyParser_ParseString(code, &_PyParser_Grammar,
+ Py_file_input, &e);
+ if (n == NULL) {
+ if (e.error == E_EOF)
+ return 0;
+ return -1;
+ }
+
+ PyNode_Free(n);
+ return 1;
+ }
+
+Un'altra soluzione e' di compilare la stringa ricevuta con
+``Py_CompileString()``. Se si compila senza errori si puo' provare ad eseguire il
+codice chiamando ``PyEval_EvalCode()``. Altrimenti si salva l'input per dopo.
+Se la compilazione fallisce si deve cercare se si tratta di un errore o se
+e' richiesto altro input estraendo il messaggio dalla tupla dell'eccezione
+e confrontandola con la stringa "unexpected EOF while parsing".
+Ecco un esempio completo che utilizza la libreria GNU readline
+(si puo' ignorare SIGINT nel richiamare readline())::
+
+ #include <stdio.h>
+ #include <readline.h>
+
+ #include <Python.h>
+ #include <object.h>
+ #include <compile.h>
+ #include <eval.h>
+
+ int main (int argc, char* argv[])
+ {
+ int i, j, done = 0; /* lengths of line, code */
+ char ps1[] = ">>> ";
+ char ps2[] = "... ";
+ char *prompt = ps1;
+ char *msg, *line, *code = NULL;
+ PyObject *src, *glb, *loc;
+ PyObject *exc, *val, *trb, *obj, *dum;
+
+ Py_Initialize ();
+ loc = PyDict_New ();
+ glb = PyDict_New ();
+ PyDict_SetItemString (glb, "__builtins__", PyEval_GetBuiltins ());
+
+ while (!done)
+ {
+ line = readline (prompt);
+
+ if (NULL == line) /* CTRL-D pressed */
+ {
+ done = 1;
+ }
+ else
+ {
+ i = strlen (line);
+
+ if (i > 0)
+ add_history (line); /* save non-empty lines */
+
+ if (NULL == code) /* nothing in code yet */
+ j = 0;
+ else
+ j = strlen (code);
+
+ code = realloc (code, i + j + 2);
+ if (NULL == code) /* out of memory */
+ exit (1);
+
+ if (0 == j) /* code was empty, so */
+ code[0] = '\0'; /* keep strncat happy */
+
+ strncat (code, line, i); /* append line to code */
+ code[i + j] = '\n'; /* append '\n' to code */
+ code[i + j + 1] = '\0';
+
+ src = Py_CompileString (code, "<stdin>", Py_single_input);
+
+ if (NULL != src) /* compiled just fine - */
+ {
+ if (ps1 == prompt || /* ">>> " or */
+ '\n' == code[i + j - 1]) /* "... " and double '\n' */
+ { /* so execute it */
+ dum = PyEval_EvalCode ((PyCodeObject *)src, glb, loc);
+ Py_XDECREF (dum);
+ Py_XDECREF (src);
+ free (code);
+ code = NULL;
+ if (PyErr_Occurred ())
+ PyErr_Print ();
+ prompt = ps1;
+ }
+ } /* syntax error or E_EOF? */
+ else if (PyErr_ExceptionMatches (PyExc_SyntaxError))
+ {
+ PyErr_Fetch (&exc, &val, &trb); /* clears exception! */
+
+ if (PyArg_ParseTuple (val, "sO", &msg, &obj) &&
+ !strcmp (msg, "unexpected EOF while parsing")) /* E_EOF */
+ {
+ Py_XDECREF (exc);
+ Py_XDECREF (val);
+ Py_XDECREF (trb);
+ prompt = ps2;
+ }
+ else /* some other syntax error */
+ {
+ PyErr_Restore (exc, val, trb);
+ PyErr_Print ();
+ free (code);
+ code = NULL;
+ prompt = ps1;
+ }
+ }
+ else /* some non-syntax error */
+ {
+ PyErr_Print ();
+ free (code);
+ code = NULL;
+ prompt = ps1;
+ }
+
+ free (line);
+ }
+ }
+
+ Py_XDECREF(glb);
+ Py_XDECREF(loc);
+ Py_Finalize();
+ exit(0);
+ }
+
+
+
+Come si cercano simboli g++ non definiti __builtin_new o __pure_virtual?
+-----------------------------------------------------------------------------------
+Per caricare i moduli di estensione g++ bisogna ricompilare Python, effettuare il relink
+utilizzando g++ (cambiando LINKCC nel Makefile dei Moludi Python) e
+effettuare il link i moduli d'estensione utilizzando il g++
+(e.g., "g++ -shared -o mymodule.so mymodule.o").
+
+
+Si possono creare classi con alcuni metodi implementati in C ed altri in Python (eg. mediante ereditarieta')?
+-----------------------------------------------------------------------------------------------------------------------------------------------------
+A partire da Python 2.2, si puo' ereditare dalle classi builtin come int, list, dict, ecc.
+
+La Boost Python Library (BPL, http://www.boost.org/libs/python/doc/index.html)
+fornisce un modo per farlo dal C++ (ad esempio e' possibile ereditare da una
+classe d'estensione scritta in C++ utilizzando il BPL).
+
+
+Perche' importando un modulo si verifica l'errore "undefined symbol: PyUnicodeUCS2*"?
+--------------------------------------------------------------------------------------------------
+Poiche' si sta utilizzando una versione di Python che utilizza
+una rappresentazione a 4 byte
+dei caratteri Unicode mentre si sta importando un modulo che e' stato compilato
+con un Python che utilizza una rappresentazione a 2 byte (che e' il default).
+
+Se il nome del simbolo non definito inizia con
+``PyUnicodeUCS4``, il problema e' l'opposto: Python utilizza caratteri
+Unicode a 2 byte ed il modulo d'estensione e' stato compilato con
+un Python che utilizza caratteri Unicode a 4 byte.
+
+Questo problema si verifica spesso utilizzando pacchetti d'estensione
+precostruiti. RedHat
+Linux 7.x, in particolare forniva un binario "python2" compilato con
+Unicode a 4 byte. Questo causa problemi di link solo se l'estensione
+utilizza una qualsiasi funzione ``PyUnicode_*()``. E' anche un problema
+se l'estensione utilizza una qualsiasi specifica di formato relativa
+agli Unicode per
+``Py_BuildValue`` (o simili) oppure una specifica di parametri per
+``PyArg_ParseTuple()``.
+
+E' possibile verificare la dimensione di un carattere Unicode sull'interprete
+Python controllando il valore di sys.maxunicode::
+
+ >>> import sys
+ >>> if sys.maxunicode > 65535:
+ ... print 'UCS4 build'
+ ... else:
+ ... print 'UCS2 build'
+
+L'unico modo per risolvere il problema e' di utilizzare moduli
+d'estensione compilati con un binario Python che utilizzi la stessa dimensione
+per i caratteri Unicode.
+
+
More information about the Commits
mailing list