
Bin Neueinsteiger, Anfänger – wie finde ich den Fehler?
Der Teufel – auch bei Python und PHP – steckt immer im Detail und trotz stundenlanger Suche findest Du selten die richtigen Antworten auf Deine Fragen. Oft hängt es daran, dass scheinbar niemand Deine Probleme hat. Mysteriös wird es für Dich, wenn eine Pythondatei in der IDLE Shell auf Deinem Computer läuft, aber nicht, wenn dasselbe Script in einem PHP Script mittels „exec“ oder „shell_exec“ aufgerufen wird.
Module, Pfade & Versionen
Bei mir auf dem Windows-PC ist Python 3.8.10 installiert, mein Webhoster legt mir leider eine ältere Version (Python 2.7) ins Paket. Das ist eine häufige Erklärung dafür, weshalb ein auf dem Computer funktionierendes Python-Skript bei Deinem Webhosting-Anbieter nicht funktioniert.
Es gibt ein Modul, das ist immer vorhanden – das Modul „sys„. Dieses Modul bietet Zugriff auf verschiedene Variablen (die von Interpreter verwendet, verwaltet werden) und auf grundlegende Funktionen. Wir nutzen dieses Modul – indirekt – für unsere Fehlersuche.
Python-Pfad ermitteln
Oft sind falsche Pfade daran schuld, dass Module nicht geladen werden und einen Fehler wie „ImportError(‚No module named requests‘,)“ erzeugen. Die richtigen Pfade in Deinem Webspace bekommst Du mit folgendem Code heraus:
import sys print(sys.path) # AUSGABE # '/homepages/38/d805973522/htdocs/d_ddr', # '/usr/lib/python2.7', # '/usr/lib/python2.7/plat-x86_64-linux-gnu', # '/usr/lib/python2.7/lib-tk', # '/usr/lib/python2.7/lib-old', # '/usr/lib/python2.7/lib-dynload', # '/usr/local/lib/python2.7/dist-packages', # '/usr/lib/python2.7/dist-packages'
Wenn der Import eines Modul/Bibliothek nicht funktioniert, kannst Du mit dem folgenden Befehl einen neuen Pfad für Deine Importe anzulegen.
sys.path.append("path-to-the-missing-directory")
Python Version des Webhosters anzeigen
Python 3 unterscheidet sich teilweise stark vom veralteten Python 2.7, sie nutzen teilweise völlig verschiedene Bibliotheken. Wenn Du einen eigenen Server gemietet hast, liegt es bei Dir, welche Python-Version Du installierst. Doch bist Du bei einem Anbieter für Web-/Shared-Hosting, wie 1blu, alfahosting, Domain Factory,Host Europe oder united domains, musst Du oft selbt die zur Verfügung gestellte Python-Version herausfinden.
Der folgende kleine Befehl zeigt Dir Deine installierte Python-Version an.
print(sys.version) # AUSGABE # 2.7.16 (default, Oct 10 2019, 22:02:15)
Fehler in Python finden und ausgeben
Wer mit PHP aufgewachsen ist, muss bei Python etwas umdenken. Damit Deine Python-Scripte trotz Fehler – beispielsweise aufgrund eines nicht geladenen Moduls – ein Lebenszeichen von sich geben, eine Fehlermeldung erzeugen, die Du anzeigen/ausgeben lassen kannst, gibt es die „try / except“ Kontrollblöcke, Strukturen.
Damit deine Python-Scripte trotz Fehler – beispielsweise aufgrund eines nicht geladenen Moduls – ein Lebenszeichen von sich geben, eine Fehlermeldung erzeugen, die Du anzeigen/ausgeben lassen kannst, gibt es die „try / except“ Kontrollblöcke, Strukturen.
In dem „try-Block“ schreibst Du den produktiven Quellcode und der „except-Block2 enthält Anweisungen für den Fall, dass etwas schiefläuft.
try: # dein Quellcode print(y) except: # wenn ein Fehler auftritt ... print('Konnte y nicht ausgeben') # AUSGABE # Konnte y nicht in der Konsole anzeigen
Es geht aber auch noch etwas genauer bei der Ausgabe aufgetretener Fehler und Problemen.
try: print(y) except Exception as e: print("Fehlermeldung:", e) # AUSGABE # Fehlermeldung: name 'x' is not defined
Die folgende Fehlermeldung dürfte bei vielen, welche über einem Webhoster ihren Webspace gemietet haben, angezeigt werden. Bei mir macht beispielsweise STRATO zicken, doch würde es mich nicht wundern, wenn Python auch bei den Webhosting Angeboten von 1und1 (IONOS, 1&1) nicht auf Anhieb funktioniert.
try: import requests head = {'User-Agent': 'Mozilla/4.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTM, like Gecko) Chrome/51.0.2704.103 Safari/537.36 '} except Exception as e: print("Fehlermeldung:", e) # AUSGABE # Fehlermeldung: ImportError('No module named requests')
Diese Ausgabe einer Fehlermeldung ist interessant – Das Modul requests konnte nicht geladen werden. Ist es nicht vorhanden? Doch, sowohl in der Python Version 2.7 als auch unter Python 3 ist dieses Modul bekannt und verfügbar. Es muss also an einem Pfad liegen, der standardmäßig nicht gesetzt ist?
Liste meiner Python Module anzeigen
Es wurde kein Modul mit dem Namen „requests“ gefunden? Okay, gibt es das Modul überhaupt in meinem Webhosting-Paket? Um mir alle verfügbaren Module auflisten zu lassen, verwende ich den Befehl:
help('modules') # AUSGABE [7] => BaseHTTPServer antigravity hmac select [8] => Bastion anydbm hotshot sets [9] => CDROM apt htmlentitydefs sgmllib [10] => CGIHTTPServer apt_inst htmllib sha [11] => Canvas apt_pkg httplib shelve [12] => ConfigParser aptsources ihooks shlex [13] => Cookie argparse imaplib shutil [14] => DLFCN array imghdr signal [15] => Dialog ast imp site [16] => DocXMLRPCServer asynchat importlib sitecustomize [17] => FileDialog asyncore imputil six [18] => FixTk atexit inspect smtpd [19] => HTMLParser audiodev io smtplib [20] => IN audioop itertools sndhdr [21] => MimeWriter base64 json socket [22] => MySQLdb bdb keyword spwd [23] => PIL binascii lib2to3 sqlite3 [24] => Queue binhex linecache sre [25] => ScrolledText bisect linuxaudiodev sre_compile [26] => SimpleDialog bsddb locale sre_constants [27] => SimpleHTTPServer bz2 logging sre_parse [28] => SimpleXMLRPCServer bzrlib lsb_release ssl [29] => SocketServer cPickle macpath stat [30] => StringIO cProfile macurl2path statvfs [31] => TYPES cStringIO mailbox string [32] => Tix calendar mailcap stringold [33] => Tkconstants cgi markupbase stringprep [34] => Tkdnd cgitb marshal strop [35] => Tkinter chunk math struct [36] => UserDict cmath md5 subprocess [37] => UserList cmd mercurial sunau [38] => UserString code mhlib sunaudio [39] => _LWPCookieJar codecs mimetools symbol [40] => _MozillaCookieJar codeop mimetypes symtable [41] => __builtin__ collections mimify sys [42] => __future__ colorsys mmap sysconfig [43] => _abcoll commands modulefinder syslog [44] => _ast compileall multifile tabnanny [45] => _bisect compiler multiprocessing tarfile [46] => _bsddb configobj mutex telnetlib [47] => _codecs contextlib mx tempfile [48] => _codecs_cn cookielib my_benzin_polen termios [49] => _codecs_hk copy netrc test [50] => _codecs_iso2022 copy_reg new textwrap [51] => _codecs_jp crypt nis this [52] => _codecs_kr csv nntplib thread [53] => _codecs_tw ctypes ntpath threading [54] => _collections curses nturl2path time [55] => _csv datetime numbers timeit [56] => _ctypes dbhash opcode tkColorChooser [57] => _ctypes_test dbm operator tkCommonDialog [58] => _curses decimal optparse tkFileDialog [59] => _curses_panel difflib os tkFont [60] => _elementtree dircache os2emxpath tkMessageBox [61] => _functools dis ossaudiodev tkSimpleDialog [62] => _hashlib distutils parser toaiff [63] => _heapq doctest pdb token [64] => _hotshot dumbdbm pickle tokenize [65] => _io dummy_thread pickletools trace [66] => _json dummy_threading pipes traceback [67] => _locale email pkgutil ttk [68] => _lsprof encodings platform tty [69] => _md5 ensurepip plistlib turtle [70] => _multibytecodec errno popen2 types [71] => _multiprocessing exceptions poplib unicodedata [72] => _mysql fcntl posix unittest [73] => _mysql_exceptions filecmp posixfile urllib [74] => _osx_support fileinput posixpath urllib2 [75] => _pyio fnmatch pprint urlparse [76] => _random formatter profile user [77] => _sha fpformat pstats uu [78] => _sha256 fractions pty uuid [79] => _sha512 ftplib pwd validate [80] => _socket functools py_compile warnings [81] => _sqlite3 future_builtins pyclbr wave [82] => _sre gasoline_polen pydoc weakref [83] => _ssl gc pydoc_data webbrowser [84] => _strptime gdbm pyexpat whichdb [85] => _struct genericpath quopri wsgiref [86] => _symtable getopt random xdrlib [87] => _sysconfigdata getpass re xml [88] => _sysconfigdata_nd gettext readline xmllib [89] => _testcapi glob repr xmlrpclib [90] => _threading_local grp resource xxsubtype [91] => _version gzip rexec zipfile [92] => _warnings hashlib rfc822 zipimport [93] => _weakref heapq rlcompleter zlib [94] => _weakrefset hgdemandimport robotparser [95] => abc hgext runpy [96] => aifc hgext3rd sched [97] => [98] => Enter any module name to get more help. Or, type "modules spam" to search [99] => for modules whose descriptions contain the word "spam".
Den Befehl schreibst Du in das Pythonskript, welches Du auf einer Website mit PHP Befehl exec() aufrufst. Das Ergebnis wird im Browser angezeigt.
Wie ich sehe, wird das Modul „requests“ nicht erwähnt.
Neue Python Pfade einfügen
Wenn Du ein Python Modul in Dein Python-Script einbindest, durchsucht Python die ihm bekannten Verzeichnisse auf der Suche nach diesem Modul. Findet Python dieses Modul in keinem der bekannten Verzeichnisse, bekommst Du Fehlermeldung „ImportError(‚No module named requests‘,)“ angezeigt.
Die Variable sys.path verwaltet Pfadinformationen in Python. Wenn ein Modul importiert werden soll, nutzut der Pythoninterpreter diese ihm bekannten Pfadinformationen.
Die Methode append() wird über das Modul sys.path bereitgestellt. Um append() zu verwenden, muss zuvor das sys-Modul importiert werden.
Mit dem folgenden Befehl sys.path.append() kannst Du Pfade inzufügen, die bei der Suche nach Modulen einbezogen werden sollen.
import sys sys.path.append('/usr/bin/python3.7') sys.path.append('/usr/lib/python3.7') sys.path.append('/usr/local/lib/python3.7') sys.path.append('/usr/lib/python3.7/dist-packages') print(sys.path)
Python prüft dabei nicht, ob diese Pfade auch tatsächlich auf Deinen Server existieren. Mit „print(sys.path)“ kannst Du Dir jetzt alle Python-Pfade anzeigen lassen.