500 Internal Server Error beim Ausführen eines CGI-Programms

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
diddus
User
Beiträge: 4
Registriert: Mittwoch 16. Mai 2012, 17:55

Hallo zusammen,
ich nutze einen Hosting-Dienst bei Celeros und habe kürzlich die folgenden code im Ordner /html/cgi-bin ausgeführt:

Code: Alles auswählen

#!/usr/bin/python
import sys
print "Content-type: text/html"
print ""
print sys.version_info
Dieser Code funktioniert einwandfrei und erzeugt folgende Ausgabe:

Code: Alles auswählen

sys.version_info(major=2, minor=7, micro=1, releaselevel='final', serial=0)
Nun habe ich ein etwas umfangreicheres Modul erstellt:

Code: Alles auswählen

#!/usr/bin/python

# database-functionality  
import sqlite3
import cgitb
cgitb.enable()

# class DataBase
# management of any type of sqlite3-database
class DataBase:
    
    def __init__(self, filePath="/data/database.dat"):
        self.__connect = sqlite3.connect(filePath)
        self.__cursor = self.__connect.cursor()
        
    def __del__(self):
        self.__connect.commit()
        self.__cursor.close()
        self.__cursor.close()
        
    # add a new table
    def addTable(self, name, format):
        command = "CREATE TABLE "
        command += (name + "(id")
        
        for formatName in format:
            command += ","
            command += formatName
        
        command += ")"
        self.__cursor.execute(command)
        self.__connect.commit()
         
    # return whole table as list of tuples
    def getTable(self, table):
        pass
    
    # delete whole table
    def delTable(self, table):
        self.__cursor.execute("DROP TABLE " + table)
        self.__connect.commit()
        
    # clear (delete all items) a table
    def clearTable(self, table):
        self.__cursor.execute("TRUNCATE TABLE " + table)
        self.__connect.commit()
    
    # add element in table
    def addElement(self, table, element):
        command = "INSERT INTO "
        command += (table + " VALUES (?")
        for i in range(len(element) - 1):
            command += ",?"
        command += ")"
        self.__cursor.execute(command, element)
        self.__connect.commit()
    
    # get only one element by its ID
    def getElementById(self, id):
        pass
    
    # delete element in table
    def delElement(self, id):
        pass
           
db = DataBase("database.dat")
db.addTable("personen", ("firstname", "lastname"))
db.addElement("personen", (1, "Martina", "Mueller"))
print("fertig")
Der Code läuft auf meinem Windows Interpreter (V. 2.7.2) ohne Probleme. Es wird eine sqlite3-Datenbank erstellt und mit den Testdaten befüllt. Auf dem Server bekomme ich aber immer einen "500 Internal Server Error". Ich weiß nicht woran es liegt, die Datei ist nun als utf-8 abgespeichert und wurde mit Aptana Studio erstellt.
Kann mir hier jemand weiterhelfen? Ich weiß mir keinen Rat.

Danke,
Diddus
BlackJack

@diddus: Was das Problem ist/war sollte im Serverlog stehen.

Der Quelltext sind nicht nach Python aus. Eher nach Java. Namenskonvention für Methoden und Variablen sind Kleinbuchstaben mit Bodenstrichen, also zum Beispiel `add_table()` statt `addTable()` und `file_path` statt `filePath`.

Für Implementierungsdetails wird *ein* führender Unterstrich verwendet. Zwei sind nicht wirklich ”private” — auch da kommt man problemlos heran wenn man weiss wie. Zwei führende Unterstriche sind zur Vermeidung von Namenskollisionen bei Mehrfachvererbung gedacht. Die setzt aber aus gutem Grund ausser in seltenen Fällen für ”Mixin”-Klassen niemand ein.

Dein Zusamensetzen von Zeichenketten ist auch kein idiomatisches Python. Es gibt eine `join()`-Methode auf Zeichenketten. Und Zeichenkettenformatierung mittels ``%``-Operator oder der `format()`-Methode auf Zeichenketten.

Die Kommentare über den Methodendefinitionen könnte man sinnvoller weise als DocStrings unter die erste Zeile schreiben.

Deine `addElement()` könnte dann zum Beispiel so aussehen:

Code: Alles auswählen

    def add_element(self, table_name, values):
        """Add given `values` to given `table`."""
        self._cursor.execute(
            'INSERT INTO %s VALUES (%s)' % (
                table_name, ','.join('?' * len(values))
            ),
            values
        )
        self._connect.commit()
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Grundsätzlich dazu noch der obligatorische Hinweis aus Web-Frameworks. Plain CGI wird idR. eher nicht mehr verwendet.

Bevor Du einen kompletten SQL-Abstraktions-Layer selber schreibst, schau Dir doch mal SQLAlchemy an :-)

Zudem ergänzend zu BlackJack:

- `__del__` verhält sich *nicht* wie ein "Destruktor" aus anderen Sprachen. Das, was Du dort erreichen willst, solltest Du besser anderes lösen (z.B. über eine Context-Manager-API - also einem Protokoll für `with`). Es gibt keine Garantie, wann `__del__` und ob es überhaupt aufgerufen wird!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
diddus
User
Beiträge: 4
Registriert: Mittwoch 16. Mai 2012, 17:55

@BlackJack
Danke für die Anmerkungen, ich werd das dann auch so umsetzen, bin eben Java gewohnt. Im Serverlog steht nicht, was das Problem ist, die Einträge sind allesamnt dehr alt:

Code: Alles auswählen

[Thu Mar 08 17:01:07 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
[Thu Mar 08 17:15:07 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
[Thu Mar 08 18:26:07 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
[Thu Mar 08 18:33:08 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
[Thu Mar 08 19:26:07 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
[Thu Mar 08 19:32:07 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
[Thu Mar 08 19:36:07 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
[Thu Mar 08 20:02:09 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
[Thu Mar 08 20:08:08 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
[Thu Mar 08 20:33:07 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
[Thu Mar 08 21:33:08 2012] [warn] RSA server certificate CommonName (CN) `linus.servertools24.de' does NOT match server name!?
Weiß jemand warum das Problem nicht im Server-Log erscheint?

@Hyperion
Wenn ich nur die fertigen Bibliotheken verwende lerne ich ja gar nichts beim entwickeln ;-).
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

diddus hat geschrieben:Wenn ich nur die fertigen Bibliotheken verwende lerne ich ja gar nichts beim entwickeln .
Ich finde das ein wenig ironisch wenn man bedenkt, dass du dafür ganze zwei Module in deinem Beispiel-Code importiert hast anstatt sie des Lerneffekts halber nachzubauen.
diddus
User
Beiträge: 4
Registriert: Mittwoch 16. Mai 2012, 17:55

@webspider
Module , die aber standardmäßig mit Python ausgeliefert werden.
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Das ändert nichts daran, dass der Vorsatz dabei etwas dazuzulernen für deinen Fall weniger sinnvoll sein wird. Gibt ja auch keine Köche, die sich aus Prinzip ihre Messer aus Stein zurechthauen um danach damit in einer Restaurant-Küche zu arbeiten. Oder etwa doch?
BlackJack

@diddus: Keine Ahnung warum ich das `__del__()` übersehen habe. :-) Bei Java gibt es die `finalize()`-Methode, welche im Grunde die gleichen Probleme hat — weswegen auch dort von deren Implementierung abgeraten wird.

In welchem Log hast Du denn nachgeschaut? Oft ist der Apache so konfiguriert, dass er verschiedene Logs schreibt, zum Beispiel für Zugriffe und für Fehler getrennte. Ein „Internal Server Error” sollte auf jeden Fall irgend wo protokolliert werden, sonst wäre die Konfiguration ziemlich schräg.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Vielleicht hilft Dir das weiter?

@diddus: Ok, dagegen ist wenig einzuwenden. Wobei es immer die Frage ist, ob man das Rad neu erfindet, oder es neu implementiert. Bei ersterem riskierst Du Fehlschläge, Fehler einzubauen und in Fallen zu laufen, die andere schon vor Dir gemacht haben, bei letzterem hast Du die Idee dahinter *vorher* studiert und versuchst das im Bewusstsein der Gefahren und Fallstricke umzusetzen.

Ich habe den Eindruck, dass Du mit den Technologien noch nicht so bewandert bist. Speziell im Bereich der Webentwicklung ist das u.U. sogar gefährlich. Unabhängig davon bist Du ja auch in Python noch ein Neuling, sowohl, was Sprache als auch was die gängige Toolchain anbelangt. Insofern halte ich es für sinnvoll, Dich auf die Standardkomponenten hinzuweisen... :roll:

Denke mal drüber nach, wie Du eine Konfigurationsdatei im YAML-Format behandeln würdest. Nach Deiner Argumentation würdest Du einen YAML-Parser selber implementieren, damit Du "etwas" lernst... läge die Datei im JSON-Format vor, könntest Du auf das "Lernen" also verzichten? ;-) (Hint: Schau Dir mal die Module dazu in der Standard-Lib an!) Krude Logik... :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
diddus
User
Beiträge: 4
Registriert: Mittwoch 16. Mai 2012, 17:55

Ok, das Problem ist gelöst, das Programm hatte keinen Schreibzugriff auf den Ordner. Hätte ich selbst drauf kommen müssen, aber danke trotzdem.
Antworten