Escribo un software en github. Básicamente es un icono de bandeja con algunas características adicionales. Quiero proporcionar un código de trabajo sin tener que hacer que el usuario instale lo que son esencialmente dependencias para funciones opcionales y no quiero importar cosas que no voy a usar, así que pensé que un código como este sería " buena solución ":¿Cuál es la buena práctica de Python para importar y ofrecer características opcionales?
---- IN LOADING FUNCTION ----
features = []
for path in sys.path:
if os.path.exists(os.path.join(path, 'pynotify')):
features.append('pynotify')
if os.path.exists(os.path.join(path, 'gnomekeyring.so')):
features.append('gnome-keyring')
#user dialog to ask for stuff
#notifications available, do you want them enabled?
dlg = ConfigDialog(features)
if not dlg.get_notifications():
features.remove('pynotify')
service_start(features ...)
---- SOMEWHERE ELSE ------
def service_start(features, other_config):
if 'pynotify' in features:
import pynotify
#use pynotify...
Sin embargo, hay algunos problemas. Si un usuario formatea su máquina e instala la última versión de su sistema operativo y vuelve a desplegar esta aplicación, las características desaparecen repentinamente sin previo aviso. La solución es presentar esto en la ventana de configuración:
if 'pynotify' in features:
#gtk checkbox
else:
#gtk label reading "Get pynotify and enjoy notification pop ups!"
Pero si esto es decir, un Mac, ¿cómo sé que no estoy enviando al usuario en una búsqueda inútil en busca de una dependencia que nunca pueden ¿llenar?
El segundo problema es el: tema
if os.path.exists(os.path.join(path, 'gnomekeyring.so')):
. ¿Puedo estar seguro de que el archivo siempre se llama gnomekeyring.so en todas las distribuciones de Linux?
¿Cómo prueban otras personas estas características? El problema con el
básicatry:
import pynotify
except:
pynotify = disabled
es que el código es global, estos podrían ser esparcidos alrededor e incluso si el usuario no desea pynotify .... Está cargado de todos modos.
Entonces, ¿qué piensan las personas que es la mejor manera de resolver este problema?
Creo que el bloque 'except ImportError' necesita establecer' external_module = None' o obtendrá un 'NameError' cuando intente acceder a él en el bloque if. – abhishekmukherg
Al igual que, intente: excepto: (sin el tipo de excepción), es un anti-patrón, la captura de ImportError puede no ser lo que desea. Si el módulo existe, pero genera una excepción, lo detectará y continuará ocultando el error. Es mucho mejor verificar primero la existencia del módulo, decidir si quieres importarlo y luego * no * manejar el ImportError – user48956