uwsgi: urllib problem

Django, Flask, Bottle, WSGI, CGI…
Antworten
horko
User
Beiträge: 17
Registriert: Dienstag 1. Oktober 2013, 10:49

Moin,

ich hab hier ein Problem wo ich mir nicht sicher bin wie man das lösen kann.
Und zwar hab ich eine Flask Application die nachschauen soll ob es ein Bild einem entfernten Webserver gibt.

Code: Alles auswählen

from urllib import urlopen
...
if IdNr:
    id_arr = []
    res0 = urlopen('http://shop.external-server.de/bilder/'+IdNr+'-0F5.jpg').getcode()
    if int(res0) == int(200):
        id_arr.append('http://shop.external-server.de/bilder/'+IdNr+'-0F5.jpg')
...
Funktioniert auch wunderbar wenn ich es ohne uwsgi laufen lassen.
Sobald ich es aber darüber laufen lasse passiert nichts.
Und ich bekomm nur die Rückmeldung: Internal Server Error

In den Logs steht nichts, kein Fehlermeldung
[pid: 4172|app: 0|req: 1/2] 192.*.*.* () {44 vars in 911 bytes} [Wed Jul 9 11:34:00 2014] POST /id_overlay => generated 291 bytes in 52 msecs (HTTP/1.1 500) 2 headers in 84 bytes (1 switches on core 0)
Muss ich bei meinen uwsgi variablen irgendwas anpassen?
Steh da wirklich etwas auf dem Schlauch.

Code: Alles auswählen

<uwsgi>
    <socket>/tmp/uwsgi.sock</socket>
    <chmod-socket>660</chmod-socket>
    <chdir>/var/www/localhost/flask/application/</chdir>
    <module>server_start</module>
    <callable>app</callable>
    <threads>10</threads>
    <processes>4</processes>
    <harakiri>600</harakiri>
    <virtualenv>/var/www/localhost/flask/env/</virtualenv>
    <pythonpath>/var/www/localhost/flask/env/</pythonpath>
    <pythonpath>/var/www/localhost/flask/env/lib/python2.7</pythonpath>
    <pythonpath>/var/www/localhost/flask/env/lib/python2.7/site-packages/</pythonpath>
    <uid>nginx</uid>
    <gid>nginx</gid>
    <vhost>true</vhost>
</uwsgi>
Hoffe hier kann Jemand etwas Licht ins Dunkel bringen.
BlackJack

@horko: Die `int()`-Aufrufe sind überflüssig. Direkt auf einem literalen `int()`-Wert ist das ja offensichtlich, aber auch die `getcode()`-Methode liefert eine Zahl die nicht noch einmal in eine Zahl umgewandelt werden muss.

Ich würde an der Stelle das `requests`-Paket empfehlen. Das legt eine wesentlich schönere API über die `urllib`(s) aus der Standardbibliothek. Es würde sich da eventuell auch anbieten einen HEAD-Request zu stellen wenn man nur wissen will ob die Datei existiert.

Beim Entwickeln mit WSGI finde ich den Werkzeug-Debugger ziemlich nützlich. Verwendest Du irgend etwas in dieser Richtung?
horko
User
Beiträge: 17
Registriert: Dienstag 1. Oktober 2013, 10:49

Danke für den Tipp mit den int()'s
Werde ich anpassen, brauch ja kein unötigen operationen.

Ne ich verwende bis dato keinen Debugger, bzw. bin ich immer gut mit dem integrierten werkzeug debugger von flask klar gekommen.
Nur leider bringt der mir an der Stelle nichts, da es ohne Probleme läuft wenn ich es direkt also ohne uwsgi als interpreter starte.

Wie funktioniert der debugger für uwsgi denn?
Hab gerade kurz geschaut aber nicht wirklich was passendens gefunden.
BlackJack

@horko: Der Funktioniert für uwsgi nicht anders als ohne, der setzt ja an der WSGI-Schnittstelle an und ist damit unabhängig von der Technologie die danach in Richtung Client kommt. Und man kann sich damit ja normalerweise Tracebackinformationen und sogar einen interaktiven Debugger mit der Fehlermeldung zum Browser ausliefern lassen. Das ”versagt” eigentlich nur wenn die Webanwendung selbst wegen gravierender Fehler, also zum Beispiel Syntaxfehler gar nicht erst ordentlich starten kann.

Noch eine kleine Bemerkung zu Pfaden: Der Apache hat unter ``/var/www/`` üblicherweise sein Document Root. Auch wenn das bei nginx erst einmal kein Problem ist, sollte man sich ganz sicher sein, dass diese Verzeichnisse nicht irgendwann einmal von einem Webserver einfach so ausgeliefert werden könnten. Kann ja sein, dass man auf dem gleichen Rechner irgendwann mal etwas installiert was Apache als Abhängigkeit hat, und nicht mehr daran denkt, dass der dann Quelltexte und eventuell sogar Konfigurationsdateien ausliefern kann, die unter dem Verzeichnis gespeichert sind.
horko
User
Beiträge: 17
Registriert: Dienstag 1. Oktober 2013, 10:49

Danke für den Hinweiß mit Apache, allerdings ist das nen gentoo system auf dem der server läuft, der weiß das er alles ohne apache abhängigkeit compilieren soll.
[werd es aber für die nächste größere wartung mit berücksichtigen]

Das Problem ist das ich das auch so kenne, wie du es beschrieben hast... na ja bis vorhin zumindest.

Wie gesagt wenn ich jetzt python server_start.py aufrufe, läuft die application genau so wie soll

Hab das ganze mal etwas mich echo gepflastert
So sieht es aus wenn ich das ganze ohne uwsgi starte:
* Running on http://127.0.0.1:5000/
* Restarting with reloader
127.0.0.1 - - [09/Jul/2014 14:49:43] "GET /id_overlay HTTP/1.1" 200 -
Form Valid
try urlopen
200
id Array filled- send to result
127.0.0.1 - - [09/Jul/2014 14:49:47] "POST /id_overlay HTTP/1.1" 200 -
So sieht das ganze bei uwsgi aus
[pid: 5641|app: 0|req: 2/4] 192.*.*.* () {40 vars in 796 bytes} [Wed Jul 9 14:53:46 2014] GET /id_overlay => generated 4157 bytes in 68 msecs (HTTP/1.1 200) 3 headers in 263 bytes (1 switches on core 6)
Form Valid
try urlopen
[pid: 5641|app: 0|req: 4/6] 192.*.*.* () {44 vars in 911 bytes} [Wed Jul 9 14:53:53 2014] POST /id_overlay => generated 291 bytes in 5031 msecs (HTTP/1.1 500) 2 headers in 84 bytes (2 switches on core 8)
Hier mal die gesammte Funktion um die es sich dreht

Code: Alles auswählen

@app.route('/sketch_overlay', methods = ['GET', 'POST'])
def sketch_overlay():
    form = SketchForm()
    form_eng = SearchForm_eng(request.form) #for eng term 

    if request.method == 'POST' and form.validate():
        SketchNr = re.sub(r'\D+', '', form.SketchNr.data)
        print 'Form Valid'
        if SketchNr:
            sketch_arr = []
            print 'try urlopen'
            res0 = urlopen('http://shop.external-server.de/bilder/'+SketchNr+'-0F0.jpg').getcode()
            print res0
            if res0 == 200:
                sketch_arr.append('http://shop.external-server.de/bilder/'+SketchNr+'-0F0.jpg')
                num = int(1)
                while True:
                    result = urlopen('http://shop.external-server.de/bilder/'+str(num)+'/'+SketchNr+'-0F0.jpg').getcode()
                    if result == 200:
                        sketch_arr.append('http://shop.external-server.de/bilder/'+str(num)+'/'+SketchNr+'-0F0.jpg')
                        num = num + int(1)
                    else:
                        break
                return render_template('sketch_overlay_result.html', sketchnr=SketchNr, sketch_arr=sketch_arr)
            else:
                flash('No Result for:' +SketchNr)
    return render_template('sketch_search.html', form=form, form_eng=form_eng)
BlackJack

@horko: Deutet ja auf ein Problem beim `urlopen()` hin. Bei einer Ausnahme sollte ja eigentlich der Werkzeugdebugger aktiv werden. Ich würde als nächstes wahrscheinlich mal per Hand ein ``try``/``except`` um die Zeile setzen und im ``except``-Zweig die Ausnahme ausgeben lassen.
horko
User
Beiträge: 17
Registriert: Dienstag 1. Oktober 2013, 10:49

Ich bin mir jetzt nicht 100% sicher was du genau meinst.
Allerdings hab ich jetzt mal folgendes versucht:

Code: Alles auswählen

try:
    res0 = urlopen('/http://shop.external-server.de/bilder/'+SketchNr+'-0F0.jpg').getcode()
    print res0
except Exception as _err:
    print _err
Diesmal gab es zumindest einen kleinen Hint, auch wenn ich noch nicht weiß ob der mir wirklich weiterhilft.

[Errno socket error] [Errno 111] Connection refused
BlackJack

@horko: Offensichtlich verweigert der abgefragte Server die Verbindung. Ist der Unterschied tatsächlich nur uwsgi oder sind das auch zwei verschiedene Rechner auf denen das funktioniert bzw. nicht funktioniert? Denkbar wäre zum Beispiel das von dem Rechner wo es funktioniert zeitlich nahe mal per Browser eine Verbindung aufgemacht wurde und Du Dich an dem Webshop angemeldet hast und der deshalb die IP kennt und erlaubt. Oder das auf dem Rechner wo uwsgi läuft irgendwo eine Firewall solche Abfragen nach aussen blockt.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@horko: Du solltest Deinen Code unbedingt mal aufräumen: Konstante Strings als Konstanten aus der Funktion herausziehen, Stringformat benutzen, doppelten Code reduzieren. Ungefähr so:

Code: Alles auswählen

from itertools import count, takewhile

SHOP_IMG_URL = 'http://shop.external-server.de/bilder/{0}-0F0.jpg'
SHOP_IMG2_URL = 'http://shop.external-server.de/bilder/{0}/{1}-0F0.jpg'

def url_generator(sketch_nr):
    yield SHOP_IMG_URL.format(sketch_nr)
    for num in count(1):
        yield SHOP_IMG2_URL.format(num, sketch_nr)

def url_exists(url):
    result = urlopen(url).getcode()
    return result == 200

@app.route('/sketch_overlay', methods = ['GET', 'POST'])
def sketch_overlay():
    form = SketchForm()
    form_eng = SearchForm_eng(request.form) #for eng term
 
    if request.method == 'POST' and form.validate():
        sketch_nr = re.sub(r'\D+', '', form.SketchNr.data)
        if sketch_nr:
            sketches = list(takewhile(url_exists, url_generator(sketch_nr)))
            if not sketches:
                flash('No Result for:' +sketch_nr)
            else:
                return render_template('sketch_overlay_result.html', sketchnr=sketch_nr, sketch_arr=sketches)
    return render_template('sketch_search.html', form=form, form_eng=form_eng)
horko
User
Beiträge: 17
Registriert: Dienstag 1. Oktober 2013, 10:49

@Sirius3: Danke werd sobald das Problem aus der Welt geschafft ist mich von deinen Vorschlägen inspirieren lassen, auch wenn ich itertools noch nie benutzt hab, aber öfters mal was neues.

@BlackJack: Ja, der einzige Unterschied ist der uwsgi/kein uwsgi
Daher gehe ich davon aus das es irgendwie ein Problem mit uwsgi ist.
Werd sobald ich etwas luft habe das ganze auf nem Rechner nachbilden der ne grafische Oberfläche hat, und dann mal mit wireshark und co schauen ob der überhaupt versucht ne verbindung aufzubauen.
Oder ob das schon daran scheitert.
horko
User
Beiträge: 17
Registriert: Dienstag 1. Oktober 2013, 10:49

Ich glaub ich hab das Problem gefunden.

Die Versuche ohne uwsgi liefen über eth0, die verbindungen von uwsgi laufen über eth1.
Werd das gleich mal schauen ob ich das ganze via routing beheben kann, bin aber recht zuversichtlich in anbetracht der hier laufenden verkorksten firewall würde mich das nicht wundern.



EDIT:
So ein kurzer Patch der routingtable und jetzt läuft es.
Sry für den falschen Alarm.
Werd mich dann mal dran machen die Verbesserungsvorschläge von Sirius zu implementieren.

Herzlichen Dank an Euch ;)
Antworten