Sta usando __import __ ('module_name') un antipattern in Python?

1

Attualmente sto rifattorizzando un progetto Python 2 che include la possibilità di aggiungere o rimuovere plugin, che sono moduli Python che implementano una determinata API.

L'app principale accede ai ganci di aggiunta / rimozione / aggiornamento nei plugin chiamando ad es. __import__('plugin_name').hook_add() dopo aver estratto i nomi dei plugin da un database, ma questo sembra un approccio hacky. Detto questo, non conosco i modi migliori per accedere ai plugin in modo programmatico.

Questo è considerato un antipattern in Python?

    
posta Jules 17.05.2016 - 14:44
fonte

1 risposta

2

Is using __import__('module_name') an antipattern in Python?

L'api per __import__ è in qualche modo fuorviante. Personalmente preferirei evitarlo dove possibile.

I documenti per lo stato di Python 3:

Direct use of __import__() is also discouraged in favor of importlib.import_module().

Ecco l'API per __import__ :

mod = __import__(
    module, # string of dotted name
    globals=None, # only needed to do relative import
    locals=None, # implementation ignores this
    fromlist=()) # fromlist just needs to be non-empty... :(
    level=0 # relative import, not going into this part
    )

Se fromlist è vuoto, si importa il modulo, ma viene restituito il pacchetto root in questo modo, quindi si deve fare la ricerca puntata per tornare ad esso:

>>> foo = __import__('foo.bar.baz')
>>> foo.bar.baz
<module 'foo.bar.baz' from /.../foo/bar/baz.py>

Questo è uguale a

>>> import foo.bar.baz
>>> foo.bar.baz
<module 'foo.bar.baz' from /.../foo/bar/baz.py>

Se vuoi solo il modulo, devi avere la lista da non vuota:

>>> baz = __import__('foo.bar.baz', fromlist=[None])
>>> baz
<module 'foo.bar.baz' from /.../foo/bar/baz.py>

Che è uguale a

>>> from foo.bar import baz
>>> baz
<module 'foo.bar.baz' from /.../foo/bar/baz.py>

>>> baz is foo.bar.baz
True

Usa importlib.import_module invece:

Ecco l'utilizzo di import_module :

>>> from importlib import import_module
>>> baz = import_module('foo.bar.baz')

È molto più bello.

    
risposta data 18.05.2016 - 17:51
fonte