Piszę oprogramowanie na Githubie. Jest to w zasadzie ikona z dodatkowymi funkcjami. Chcę dostarczyć działający fragment kodu bez konieczności instalowania użytkownika, co jest w istocie zależnościami dla opcjonalnych funkcji i nie chcę importować rzeczy, których nie zamierzam używać, więc pomyślałem, że kod taki będzie " dobre rozwiązanie ":Co to jest dobra praktyka Pythona do importowania i oferowania opcjonalnych funkcji?
---- 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...
Istnieje jednak kilka problemów. Jeśli użytkownik formatuje swój komputer i instaluje najnowszą wersję swojego systemu operacyjnego, a następnie ponownie uruchamia tę aplikację, funkcje nagle znikają bez ostrzeżenia. Rozwiązaniem jest przedstawienie tego w oknie konfiguracji:
if 'pynotify' in features:
#gtk checkbox
else:
#gtk label reading "Get pynotify and enjoy notification pop ups!"
Ale jeśli jest to powiedzieć, Mac, skąd mam wiedzieć, nie jestem wysyłania użytkownikowi na dzikie gęsi pościg szuka uzależnienia oni nigdy nie może napełnić?
Drugim problemem jest:
if os.path.exists(os.path.join(path, 'gnomekeyring.so')):
problem. Czy mogę mieć pewność, że plik jest zawsze nazywany gnomekeyring.so we wszystkich dystrybucjach Linuksa?
W jaki sposób inne osoby testują te funkcje? Problem z podstawowego
try:
import pynotify
except:
pynotify = disabled
jest to, że kod ma charakter globalny, to może być pełno dookoła, a nawet jeśli użytkownik nie chce pynotify .... to i tak załadowany.
Co zatem ludzie uważają za najlepszy sposób rozwiązania tego problemu?
Myślę, że blok "exceptException" musi ustawić 'external_module = None' lub otrzymasz' NameError' przy próbie dostępu do niego w bloku if. – abhishekmukherg
Podobnie jak, spróbuj: z wyjątkiem: (bez typu wyjątku), jest to wzorzec przeciwny, przechwytywanie ImportError może nie być tym, czego potrzebujesz. Jeśli moduł istnieje, ale zgłasza wyjątek, złapiesz go i kontynuujesz, ukrywając błąd. Znacznie lepiej jest najpierw sprawdzić istnienie modułu, zdecydować, czy go zaimportować, a następnie * nie * obsłużyć ImportError – user48956