[Python] Funzioni come moduli
Daniele Varrazzo
piro a develer.com
Mar 1 Lug 2008 00:49:02 CEST
Alessandro Dentella ha scritto:
>> A me non sembra che il global namespace del chiamante venga inquinato:
>>
>> In [1]: ENV = {}
>>
>> In [2]: execfile('plugin_A.py', ENV)
>>
>> In [3]: a = ENV['A']()
>>
>> In [4]: a.test()
>> [ ...roba... ]
>>
>> In [5]: sys
>>
>> ---------------------------------------------------------------------------
>> <type 'exceptions.NameError'> Traceback (most recent call
>> last)
>>
>> /home/piro/py/<ipython console> in <module>()
>>
>> <type 'exceptions.NameError'>: name 'sys' is not defined
>
>
> mi arrendo... il che mostra che non ho compreso bene il significato di
> questo dizionario e tantomeno comprendo cosa succeda in realtà se uso due
> dizionari (globals, locals) e se ne uso uno soltanto...
>
> Questo utilizzo è quindi completamente equivalente ad un import?
:) questa discussione l'ho già vissuta meno di un mese fa in una ML di amici
smanettoni...
Puoi ottenere lo stesso scopo: esecuzione dinamica del codice, ma gli
strumenti non sono equivalenti.
__import__ ha una semantica _perfettamente documentata_, ma che a leggerla
senza pensare al contesto a cui serve sembra assurda. Per esempio che
__import__('foo.bar.baz') restituisce foo ma come effetto collaterale carica
bar e baz. Come anche il significato criptico dei parametri.
In realtà __import__ è solo l'hook implementativo dello statement import, e la
sua semantica è quella dello statement. E' esposta solo per permettere
(immagino rimpiazzandola ma non lo so) gli hook ad import time. Porta con sé
tutti gli effetti dell'import, che nel contesto di scrivere un sistema di
plugin sono scomodi: per esempio devi avere la directory contenitore nel
pythonpath, o che __import__() non ricarica i moduli, ma devi usare reload()
(che non è ricorsiva e fare ereditarietà tra i plugin diventa ancora più
delicato). Tutti problemi superabili, ma che fanno capire che non è questo lo
scopo per cui la funzione è progettata.
La funzione execfile() è esposta all'API pubblica (le funzioni __così__ lo
sono, ma sono progettate allo scopo di essere usate in maniera peculiare dal
linguaggio) e la sua semantica è esplicita: tu crei un namespace, chiedi di
eseguire il contenuto di un modulo in quel contesto e, dopo l'esecuzione, hai
a disposizione il namespace con il contenuto modificato (nuovi oggetti o stato
alterato). Mi sembra adeguato allo scopo di creare plugin, no?
Poi __import__ ha il suo bello (Valentino Volonghi ha citato la funzione
namedAny() di Twisted, che la usa per importare dinamicamente qualunque
oggetto dai moduli), ma se ho a disposizione due funzioni: una pubblica, con
la semantica adatta al mio scopo e una, progettata per altri scopi, che con
gli aggiustamenti giusti può fare al caso mio, allora in mancanza di altri
problemi preferisco usare la prima.
--
Daniele Varrazzo - Develer S.r.l.
http://www.develer.com
Maggiori informazioni sulla lista
Python