Datei mit mechanize im .htaccess-Bereich hochladen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo Leute,

ich versuche gerade mit mechaniz im .htaccess-Bereich eine Datei hochzuladen. Auf meinem Webserver habe ich einen Ordner Passwort geschützt. Dort liegt eine PHP-Seite, die die Datei hochlädt. Das PHP-Script funktioniert tadellos. Wenn ich das nachfolgende, ausführbare Programm ausführe, dann bekomme ich einen Traceback (am Ende meines Beitrages zu finden). Aber merkwürdig ist: Sobald ich br.submit() auskommentiere, dann klappt es. Über Print wird mir dann der "HTML-Quelltext" ausgegeben (siehe am Ende des Beitrages). Das heißt, mechanize hat schon mal Zugang zum .htaccess-Bereich. Irgendwie komme ich nicht weiter. Habt ihr eine Idee?

Ihr könnt es gerne testen, der Benutzername test, das Passwort test und die url sind gültig und korrekt. Ich habe extra für euch diesen Bereich eingerichtet, damit ihr es testen könnt.

Code: Alles auswählen

from mechanize import Browser

def access_atuh(url = None,
                user = None,
                pwd = None,
                file_path = None):
    br = Browser()
    br.add_password(url, user, pwd)
    response = br.open(url)
    br.select_form(nr=0)
    br.form.add_file(open(file_path,'rb'))
    #br.form.add_file(open(file_path), 'text/plain', file_path)
    br.submit()
    print response.read()

access_atuh(url = "http://sophus.bplaced.net/xarphus_support/support_account/test/upload_form.php",
            user = "test",
            pwd = "test",
            file_path = r'C:\path\to\YourImage.jpg')
Traceback (most recent call last):
File "C:\Users\Sophus\Desktop\http_mechnaize\hppt_mechanize.py", line 20, in <module>
file_path = r'C:\Users\Sophus\Desktop\Buehne.jpg')
File "C:\Users\Sophus\Desktop\http_mechnaize\hppt_mechanize.py", line 13, in access_atuh
res = br.submit()
File "C:\Python27\lib\site-packages\mechanize\_mechanize.py", line 685, in submit
return self.open(self.click(*args, **kwds))
File "C:\Python27\lib\site-packages\mechanize\_mechanize.py", line 254, in open
return self._mech_open(url_or_request, data, timeout=timeout)
File "C:\Python27\lib\site-packages\mechanize\_mechanize.py", line 310, in _mech_open
raise response
httperror_seek_wrapper: HTTP Error 401: Unauthorized
Sobald ich den br.submit() auskommentiere, wird mir folgendes über Print ausgegeben:
<!-- on liner comment -->
<form action="upload.php" method="post" enctype="multipart/form-data">

<input type="file" name="datei"><br>

<input type="submit" name="upload" value="Upload">
Benutzeravatar
__blackjack__
User
Beiträge: 14135
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich würde jetzt mal wild raten und sagen Du hast Benutzer und Passwort für die URL mit dem Formular gesetzt, aber nicht für die URL die dann den Upload entgegen nehmen soll. Also ich würde mal versuchen die Angaben für ``http://sophus.bplaced.net/xarphus_suppo ... ount/test/`` ohne das ``upload_form.php`` hinten dran zu setzen.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@__blackjack__: Hast du die Bild-Datei hochgeladen? Auf meinem Webserver liegt ein Bild :) Ich werde es gleich mal versuchen.

Was ich nicht ganz verstehe ist, dass die URL (http://sophus.bplaced.net/xarphus_suppo ... d_form.php) den Upload doch entgegen nimmt. Denn in der Form wird die Datei entgegen genommen und mittels PHP weiter verarbeitet.
nezzcarth
User
Beiträge: 1778
Registriert: Samstag 16. April 2011, 12:47

Sophus hat geschrieben: Samstag 30. Juni 2018, 15:51 Was ich nicht ganz verstehe ist, dass die URL (http://sophus.bplaced.net/xarphus_suppo ... d_form.php) den Upload doch entgegen nimmt. Denn in der Form wird die Datei entgegen genommen und mittels PHP weiter verarbeitet.
Nein, das ist nicht der Fall. Das Formular 'upload_form.php' ist nur eine vorgelagerte Schnittstelle und hat mit dem Upload nicht viel zu tun. Solche Formulare sind oft zweistufig aufgebaut: einmal hat man die Seite mit den Formularelementen, die man im Browser sieht und einmal den Server-seitigen Handler, der die Arbeit macht. Den eigentlichen Upload nimmt also das Script entgegen, das im action-Attribut des Formulars steht, d.h. 'upload.php'. Was du mit deinem Script ja effektiv machen möchtest, ist das Browser-Formular 'upload_form.php' durch ein Skript zu ersetzen. Also schickst du (per HTTP-Post Request) die Dateien direkt an den Upload Handler.

(".htaccess-Bereich" ist übrigens kein existierender, sinnvoller Begriff. htaccess-Dateien bieten einfach einen Mechanismus des Apache-Servers, um Benutzern eine Möglichkeit zu geben, Teile der Konfiguration zu überschreiben, ohne die zentrale Konfiguration ändern zu müssen. Darin kann kann alles Mögliche stehen.)
Zuletzt geändert von nezzcarth am Samstag 30. Juni 2018, 16:35, insgesamt 1-mal geändert.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Ich habe __blackjacks__ Anmerkungen berücksichtigt und mein Programm dementsprechend angepasst:

Code: Alles auswählen

from mechanize import Browser

def access_atuh(protected_url = None,
                upload_url = None,
                user = None,
                pwd = None,
                file_path = None):
    '''
       NOTICE
       ======
       This function is used to upload an image file.

       PARAMETERS:
       ===========
       :protected_url   -   Here we just the clear url to the protected area, not to the upload-page.

       :upload_url      -   We ecxept a url to the formular, which initialize the upload. 

       :user            -   The user name of this protected area.

       :pwd             -   Password is import to login to protected area successfully.

       :file_path       -   We need the path to the image file which we would to upload it.
       
       :return          -   Nothing is returned. The statement 'return'
                            terminates a function. That makes sure that the
                            function is definitely finished.
    '''
    br = Browser()
    br.add_password(protected_url, user, pwd)
    response = br.open(upload_url)

    # There is a form without name.
    br.select_form(nr=0)
    br.form.add_file(open(file_path,'rb'), 'images', file_path, name = 'datei') # Name is here the name of input field on webpahe
                                                                                # In this case the input field is just called 'datei' 
    res = br.submit()

    return

access_atuh(protected_url = "http://sophus.bplaced.net/xarphus_support/support_account/test/",
            upload_url = "http://sophus.bplaced.net/xarphus_support/support_account/test/upload_form.php",
            user = "test",
            pwd = "test",
            file_path = r'Buehne.jpg'
            )
Sirius3
User
Beiträge: 18299
Registriert: Sonntag 21. Oktober 2012, 17:20

Abgesehen vom Problem sollte man keine Datenbanken in einen Bereich legen, der vom Webserver veröffentlicht werden kann: http://sophus.bplaced.net/sqlite_test/vertrieb.sqlite
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@Sirius3: Es sind nur Test-Datenbanken. Aber trotzdem danke für den Hinweis.
Benutzeravatar
__blackjack__
User
Beiträge: 14135
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sophus: `access_atuh()` ist vom Buchstabendreher mal abgesehen, kein passender Name für die Funktion.

Die ganzen `None`\s als Defaultargumente machen keinen Sinn. Kann man denn überhaupt irgendeinen davon weg lassen? Wenn man ein Argument beim Aufruf nicht weglassen kann, dann macht ein Defaultwert keinen Sinn, weil der dann ja niemals genutzt wird.

Der Docstring ist komisch formatiert/ausgezeichnet. Welches Werkzeug kann denn mit *der* Auszeichnung etwas sinnvolles anfangen?

Warum die normale Beschreibung der Funktion mit der Überschrift „NOTICE“ versehen ist, verstehe ich nicht. Die erste Zeile/der erste Absatz enthält normalerweise die Zusammenfassung. Eventuell gefolgt von einer umfangreicheren Beschreibung in weiteren Absätzen. Mit Überschriften die nicht speziell gesetzt werden, wäre ich sehr sparsam.

`return` ist kein Parameter. Und alles nach dem ersten Satz der Beschreibung gehört nicht in die Dokumentation von der Funktion weil das dort vollkommen irrelevant ist. Das die ``return``-Anweisung die Ausführung einer Funktion beendet braucht man überhaupt nicht dokumentieren, das steht in der Python-Dokumentation und gehört zu den absoluten Grundlagen. Der letzte Satz ist absurd. Das ``return`` stellt gar nichts sicher, weil genau das gleich auch ohne das ``return`` passieren würde. Das ist einfach nur extrem unnötig.

Dateien die man öffnet, sollte man auch wieder schliessen. Du verlässt Dich da auf Interna der Speicherverwaltung von CPython, dass das zeitnah passiert. Das ist aber nicht garantiert.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@__blackjack__: Ich arbeite grundsätzlich mit Schlüsselargumenten. So weißt man beim Aufruf der Funktion, für was welche Werte übergeben werden. Ohne Schlüsselargumente wirkt es sonst auf mich wie "Joah, ich übergebe hier und da was, aber keine Peilung für was das gut tun soll, kann es höchstens erraten". Ich liebe explizite Angaben. Schafft Transparenz. Es ist für mich einfach praktischer. Und die Docstring-Formatierung habe ich mal von einem anderen Projekt abgeschaut. Ist ewig her. Da durchwühlte ich auf GitHub in einem Projekt und fand die Formatierung optisch für mich ansprechend. Und dass das 'return' keine Zauberei hervorruft, weiß ich. Aber das gibt mir in gewissenweise ein sicheres Gefühl. So sagt mein Verstand "So, da sitzt jetzt ein return, und damit ist es endgültig vorbei". Ist für mich ein gedanklicher Schlussstrich. Und das mit dem Schließen der Datei. Ich nahm an, dass mechanize darum kümmert, nachdem er geöffnet und lesend darauf zugegriffen hat, um diese dann weiterzuleiten. Dann muss ich wohl selbst Hand anlegen. Danke für den Hinweis. Werde ich gleich in Angriff nehmen.
Sirius3
User
Beiträge: 18299
Registriert: Sonntag 21. Oktober 2012, 17:20

Schlüsselargumenten sind was ganz anderes als Defaultwerte für Parameter. Lass diese ganzen »= None« bei der Funktionsdefinition einfach weg, die machen wirklich nichts sinnvolles.

BlackJack ging es auch hauptsächlich darum, dass Du `return` so dokumentierst, als ob es ein Argument wäre und dort auch Selbstverständlichkeiten stehen.

Warum verwendest Du eigentlich Mechanize statt requests, da es für das, was Du vorhast, das falsche Werkzeug ist?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was lernt man denn über die Argumente wenn der default wert None ist? Das hat doch null Informationsgehalt. Und selbst wenn es andere Typen sind - Der Leser denkt in dem Moment, die Angaben sind nicht verpflichtend, und fällt auf die Nase. Und “explizit” ist das doch genau nicht. Es sind im Gegenteil implizite Werte, die gewählt werden, wenn nix anderes angegeben wird.

Und da du mehr Code liest als schreibst, und auch von dritten, solltest du dir diese return Geschichte abgewöhnen. Du trainierst dir damit ein Muster an, das außer dir keiner nutzt, und das dich dann weniger schnell betgreifen lässt, was anderer Code macht. Was genauso für die Argumente gilt.
Benutzeravatar
__blackjack__
User
Beiträge: 14135
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sophus: Bist Du sicher das der Docstring da *so* formatiert war und nicht ein klein wenig anders, zum Beispiel im Numpy-Stil, damit Sphinx + napoleon-Erweiterung damit auch was anfangen können‽ Siehe Beispiel: https://sphinxcontrib-napoleon.readthed ... e-vs-numpy
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@ __blackjack__: Ich muss leider gestehen, ich weiß nicht mehr wo ich es abgeguckt habe. Aber dein Beispiel ist schon sehr nahe. Aber was mich verwundert, ist, dass euch meine DocString-Formatierung gehörig auf den Sender geht. Ich dachte nicht, dass es einem so auf die Palme bringen kann. Gibt es eine gute, verständliche Seite, die einem grundlegend lehrt, wie man DocStrings formatiert?

@ __deets__: Explizit habe ich so definiert, dass man genau die Schlüsselargumente aufrufen muss, also genau weiß was man da macht und nicht einfach die Argumente stillschweigend rüberschiebt. Die Schlüsselargumebte geben mit auch Flexibilität. Ich muss die Argumente nicht in der strikten Reihenfolge übergeben. Und wieso stört euch die Return-Geschichte so ungeheuerlich? Ich will keine Grundsatzdiskussion starten. Aber ist es nicht relativ egal ob da jemand den nacktrn return setzt oder nicht? Das macht den Quelltext mit dem einen return doch nicht gleich unleserlich? Ich habe es womöglich falsch dokumentiert, dass gebe ich zu. Nur verstehe ich nicht, wieso man mich mit der Peitsche jagen will? Ich verstehe nur, dass ihr es mir aus dem Kopf treiben wollt, aber ich verstehe nur nicht warum?
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Um die Explizitheit, so wie ich sie definiere, nachvollziehbar zu machen, möchte ich es nochmals demonstrieren.

Angenommen, wir rufen folgende pseudonyme Funktion/Methode auf:

Code: Alles auswählen

volume_quarder_berechnen(3, 2, 4)
Was mich hier stört, ist, dass ich irgendwelche Zahlen übergebe, aber nicht wirklich weiß, für was welche Zahl ist. Die Zahlen stehen für mich einfach nur aneinander gereiht da. Hier werden sie einfach stillschweigend rüber geschoben, so nach dem Motto "Hier, hast du die Zahlen".

Code: Alles auswählen

volume_quarder_berechnen(laenge = 3, breite = 2, hoehe = 4)
Damit bin ich sehr zufrieden, ich weiß nun, für was die einzelnen Werte sind. Ich sehe explizit, dass die 3 für die Länge ist, die 2 für die Breite und die 4 für die Höhe. Ohne die Funktion jetzt zu sehen und zu kennen, weiß ich wesentlich mehr, was mit den Zahlen auf sich hat. Auf mich wirkt es leserlich. Und wenn ich lustig bin, kann ich die Argumente auch so übergeben wie ich es möchte, vielleicht zuerst die Höhe und dann die Länge und zum Schluss die Breite? Jedenfalls muss ich beim Lesen dieses Aufrufes nicht zu der entsprechenden Funkion/Methode springen um zu sehen, was es mit den Argumenten auf sich hat. Und aus diesem Grund "missbrauche" ich die Schlüsselargumente. Ich weiß, dass sie ursprünglich dazu gedacht ist, um Standardwerte zu setzen, wenn der Benutzer sie nicht ändert.
Benutzeravatar
__blackjack__
User
Beiträge: 14135
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sophus: Wie man DocStrings formatiert, hängt davon ab welches Werkzeug mit welchen Einstellungen man verwendet um daraus Dokumentation zu erstellen. Durchgesetzt hat sich Sphinx, also das Werkzeug welches auch für die Python-Dokumentation verwendet wird.

Es regt mich nicht auf, ich wundere mich nur warum das so ähnlich wie eine Auszeichnungssprache aussieht, aber eben nicht ist. Also warum es *fast* reStructuredText ist. Warum mal eine Überschrift mit Doppelpunkt und mal eine ohne. Warum die Parameternamen mit einem Doppelpunkt beginnen, aber danach dann keiner mehr kommt, womit das eine korrekte „field list“ in reStructuredText wäre, wo dann aber die `-` vor dem Text überflüssig wären, beziehungsweise sind das dann Listen mit jeweils nur einem einzigen Punkt. Wenig sinnvoll.

Die Sphinx-Dokumentation erklärt fast komplett reStructuredText und welche Konstrukte für Sphinx eine besondere Bedeutung haben und welche Direktiven Sphinx zusätzlich zu reinem reStructuredText kennt. Wenn man den Google- oder Numpy-Stil mehr mag als die reStructuredText-„field lists“, hat Sphinx die `napoleon`-Erweiterung, die daraus dann reStructuredText macht, den Sphinx dann verarbeiten kann. Ansonsten gibt es noch etwas im Style Guide for Python Code zu DocStrings.

Das mit den Defaultwerten macht immer noch keinen Sinn. Und Deine Erklärung dafür auch nicht. Der Aufrufer kann das ganz normal mit Positionsargumenten aufrufen, oder mit Schlüsselwortargumenten, oder mit einer Mischung, ganz wie er mag. Die ganzen unsinnigen und *verdammt irreführenden* `None`-Defaultwerte haben darauf keinen Einfluss. Das einzige was die ausser Leserverwirrung bewirken, ist das man einzelne Argumente beim Aufruf auch *weglassen* kann ohne das einem Python nicht direkt beim Aufruf(versuch) ganz klar sagt, das man nicht alle nötigen Argumente übergeben hat. Man kann die Funktion sogar ganz ohne Argumente aufrufen. Nur das es dann später kracht, weil `None` bei den meisten Argumenten keinen Sinn macht, weil der weiterführende Code nichts damit anfangen kann. Einzig das letzte Argument, `file_path`, ist tatsächlich optional und kommt auch mit `None` klar.

Für mich macht das ``return`` den Code in so weit unleserlich als ich mich frage warum das da völlig sinnlos steht. Mit der Dokumentation zusammen deutet das auf ein komisches bis falsches Verständnis davon hin wie Python funktioniert. Genau wie Deine Erklärungsversuche für die `None`-Defaultwerte.

`images` ist übrigens kein registrierter MIME-Type und HTTP will AFAIK auch den Untertyp, falls Du `image` gemeint hattest. Letztlich braucht man den hier aber auch gar nicht, Du fährst besser wenn `mechanize` den selbst ermittelt.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Tholo
User
Beiträge: 177
Registriert: Sonntag 7. Januar 2018, 20:36

Sophus hat geschrieben: Sonntag 1. Juli 2018, 02:11 Um die Explizitheit, so wie ich sie definiere, nachvollziehbar zu machen, möchte ich es nochmals demonstrieren.

Angenommen, wir rufen folgende pseudonyme Funktion/Methode auf:

Code: Alles auswählen

volume_quarder_berechnen(3, 2, 4)
Was mich hier stört, ist, dass ich irgendwelche Zahlen übergebe, aber nicht wirklich weiß, für was welche Zahl ist. Die Zahlen stehen für mich einfach nur aneinander gereiht da. Hier werden sie einfach stillschweigend rüber geschoben, so nach dem Motto "Hier, hast du die Zahlen".

Code: Alles auswählen

volume_quarder_berechnen(laenge = 3, breite = 2, hoehe = 4)
Damit bin ich sehr zufrieden, ich weiß nun, für was die einzelnen Werte sind. Ich sehe explizit, dass die 3 für die Länge ist, die 2 für die Breite und die 4 für die Höhe. Ohne die Funktion jetzt zu sehen und zu kennen, weiß ich wesentlich mehr, was mit den Zahlen auf sich hat. Auf mich wirkt es leserlich. Und wenn ich lustig bin, kann ich die Argumente auch so übergeben wie ich es möchte, vielleicht zuerst die Höhe und dann die Länge und zum Schluss die Breite? Jedenfalls muss ich beim Lesen dieses Aufrufes nicht zu der entsprechenden Funkion/Methode springen um zu sehen, was es mit den Argumenten auf sich hat. Und aus diesem Grund "missbrauche" ich die Schlüsselargumente. Ich weiß, dass sie ursprünglich dazu gedacht ist, um Standardwerte zu setzen, wenn der Benutzer sie nicht ändert.
Ich verstehe glaube ich dein Vorhaben mit der Bezeichnung von Länge,Breite,Höhe. Aber dazu brauchst du doch kein "None wert"
Ich hab hier mal ein Screenshot von deiner Funktion ohne None Werte. Und Pycharm zeigt mir sofort dein Docstring und auch deine Schlüsselattribute ohne das None vergeben wurde.
Es ist also wirklich nicht notwendig "None" zu vergeben. Nagel mich allerdings nicht fest. Ich weiß nicht wie sich das in anderen Texteditoren verhält, ich gehe aber mal von aus, das der Vorschlag der Schlüsselargumente gleich sein sollte.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sophus du wirst hier nicht gepeitscht. Du hast aber offensichtlich teilweise falsche Vorstellungen über die Semantik von Python, und bewertest Eigenschaften der Sprache so anders, das es zu Missverständnissen mit anderen Programmierern kommt. Uns in diesem fall. Und da wir dir helfen sollen, und dazu über Code reden, ist es durchaus relevant, solche Dinge anzusprechen.

Bei deinem explizite-Argumente Ding zb hast du komplett falsch verstanden, wie Python funktioniert. Wenn du eine explizite angabe von Parameter-Namen willst (was ich durchaus auch mache, selbst wenn es nicht nötig wäre, um die aufrufende Seite klarer verständlich zu machen), mach das gerne.

Es hat nur absolut nichts mit keyword Argumenten zu tun:

Code: Alles auswählen

>>> def foo(a, b):
...     print(a, b)
...     
>>> foo(b=10, a=20)
20 10
Gleichzeitig kann man natürlich problemlos so arbeiten:

Code: Alles auswählen

>>> def bar(x=1, y=2):
...     print(x, y)
...     
>>> bar(10, 20)
10 20
Du hast also bezüglich deines wunsches explizite Argumente einzuführen genau NICHTS erreicht. Im Gegenteil, denn wie schon diverse Male von mir und anderen erwähnt: jetzt kann man was vergessen, und Python warnt nicht, aber es kracht halt später oder verursacht subtile Probleme.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Ich habe mein Quellcode etwas überarbeitet und einige Anmerkungen übernommen. Nur einzig und allein die 'return'-Angelegenheit bleibt bestehen :) Das hat sich bei mir von Anbeginn eingebürgert. Und wegen einer Zeile wird nun der Lesefluss des Quelltextes nun nicht erheblich eingeschränkt.

@__deets__: Jetzt kapiere ich, was mir Sirius3, Tholo und __blackjack__ mir mitteilen wollen. Ich hatte die Python-Syntax tatsächlich falsch verstanden. Ich lernte bisher so, dass man bei Positionsargumenten die Argumente einfach so übergibt - ohne Angaben von Parameternamen. Jetzt macht es klick.

@__blackjack__: Bezüglich der Formatierung des DocStrings muss ich noch hinzufügen, dass mir gestern Abend noch einfiel, dass meine Formatierung eine Mischung ist. Es gab nicht nur EIN Projekt, sondern ich habe die DocString-Formatierungen von mehreren Projekten abgekuckt. Bei einem Projekt wurden die Überschriften verwendet, beim anderen eben nicht. Jedenfalls habe ich, wie du zu Recht erkannt hast, meine DocString-Formatierung händisch formatiert. Es gibt bei mir kein Werkzeug für. Bei jeder Funktion, die ich definiere, kopiere ich das vorherige DocString und passe sie dann in der neuen Funktion an. Ich habe deine Anmerkungen teilweise berücksichtigt. Doppelpunkte sind bei Überschriften verschwunden und die einzelnen Parameter haben am Anfang und am Ende einen Doppelpunkt und die Parameter bekommen die Type-Bezeichnungen. Ich denke, so kann ich mich sehen lassen. Im Grunde kann ich es eh nicht jedem vom Geschmack recht machen.

Code: Alles auswählen

from mechanize import Browser
    
def upload_file_basic_auth(protected_url,
                           upload_url,
                           user,
                           pwd,
                           file_path):
    '''
       SUMMARY
       =======
       This function is used to upload file.

       EXTENTED DISCRIPTION
       ====================
       This function not only uploads files, but also access a HTTP Basic authenticated page.

       PARAMETERS
       ==========
       :protected_url (str):    Here we just the clear url to the protected area, not to the upload-page.

       :upload_url (str):       We ecxept a url to the formular, which initialize the upload. 

       :user (unicode):         The user name of this protected area.

       :pwd str (unicode):      Password is import to login to protected area successfully.

       :file_path (unicode):    We need the path to the image file which we would to upload it.

       RETURNS
       =======
       :return:                 Nothing is returned. Well I know a simple 'return' isn't necessary, but this statement gives
                                me a better feeling, that says: 'return' terminates a function definitely.
    '''
    br = Browser()
    # Ignore robots.txt.  Do not do this without thought and consideration.
    br.set_handle_robots(False)
    br.add_password(protected_url, user, pwd)
    response = br.open(upload_url)

    # There is a form without name.
    br.select_form(nr=0)
    br.form.add_file(open(file_path,'rb'), "text/plain", file_path, name = 'datei') # Name is here the name of input field on webpahe
                                                                                # In this case the input field is just called 'datei' 
    res = br.submit()
    
    return

upload_file_basic_auth(protected_url = "http://sophus.bplaced.net/xarphus_support/support_account/test/",
                       upload_url = "http://sophus.bplaced.net/xarphus_support/support_account/test/upload_form.php",
                       user = u"test",
                       pwd = u"test",
                       file_path = u'test_2.rar')
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Also, __blackjack__ hat mich darauf hingewiesen, dass, sobald man eine Datei öffnet, diese auch geschlossen werden muss. In Bezug auf Mechanize habe ich mir einige Beispiele angeschaut, wo Dateien hochgeladen werden. In keinem der bisherigen Beispiele wurde die geöffnete Datei von seiten des Programmierers geschlossen. Vor diesem Hintergrund nahm ich an, dass sich Mechanize darum kümmert. Aber sei es drum. Ich habe zur Sicherheit mit der with-Anweisung begnügt, um sicher zu gehen, dass die Datei automatisch geschlossen wird. Dies sieht wie folgt aus:

Code: Alles auswählen

from mechanize import Browser
    
def upload_file_basic_auth(protected_url,
                           upload_url,
                           user,
                           pwd,
                           file_path):
    '''
       SUMMARY
       =======
       This function is used to upload file.

       EXTENTED DISCRIPTION
       ====================
       This function not only uploads files, but also access a HTTP Basic authenticated page.

       PARAMETERS
       ==========
       :protected_url (str):    Here we just the clear url to the protected area, not to the upload-page.

       :upload_url (str):       We ecxept a url to the formular, which initialize the upload. 

       :user (unicode):         The user name of this protected area.

       :pwd str (unicode):      Password is import to login to protected area successfully.

       :file_path (unicode):    We need the path to the image file which we would to upload it.

       RETURNS
       =======
       :return:                 Nothing is returned. Well I know a simple 'return' isn't necessary, but this statement gives
                                me a better feeling, that says: 'return' terminates a function definitely.
    '''
    br = Browser()
    # Ignore robots.txt.  Do not do this without thought and consideration.
    br.set_handle_robots(False)
    br.add_password(protected_url, user, pwd)
    response = br.open(upload_url)

    # There is a form without name.
    br.select_form(nr=0)
    with open(file_path,'rb') as file_object:
        br.form.add_file(file_object = file_object,
                         content_type = "text/plain",
                         filename = file_path,
                         name = 'datei') # Name is here the name of input field on webpahe
                                         # In this case the input field is just called 'datei' 
        res = br.submit()
        
    return

upload_file_basic_auth(protected_url = "http://sophus.bplaced.net/xarphus_support/support_account/test/",
                       upload_url = "http://sophus.bplaced.net/xarphus_support/support_account/test/upload_form.php",
                       user = u"test",
                       pwd = u"test",
                       file_path = u'test_2.rar')

Benutzeravatar
__blackjack__
User
Beiträge: 14135
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mechanize ruft einzig und alleine die `read()`-Methode auf dem Objekt auf und nichts anderes. Man kann da also ein beliebiges Objekt mit dieser Methode als Argument übergeben.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Antworten