wget ausgabe in Variable??

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.
Antworten
joerg-harrer
User
Beiträge: 2
Registriert: Samstag 2. Mai 2020, 11:52

Hallo, um es kurz zu machen.. Meine ersten "Gehversuche" in Python.

Ich habe folgende Frage.

ich komme von der Linux seite, hab da schon Jahrelang mit bash herumgetan und hab mir vor kurzem QT5 und Python angeschaut.

Ist es möglci, die wget.download(url) so verwenden , das die Ausgabe gleich in eine Variable kommt und keine datei auf platte legt?

Ich hab das in bash so hingebracht :
<SNIP>
cmd="wget http://apache:8080/api/getPlainValue/11131"
x=$(wget -q -O - $cmd)
if [ "$x" == "true" ] ; then
cmd="wget http://apache:8080/api/set/11131/?value=0"
else
cmd="wget http://apache:8080/api/set/11131/?value=1"
fi
x=$(wget -q -O - $cmd) 2&> /dev/null
</SNIP>

In Phyton3 hab ich jetzt um das Ding zum laufen zu bringen , ein paar sehr unschöne Dinge gemacht ...
<SNIP>
cmd = "http://apache:8080/api/getPlainValue/11131"
filename = wget.download(cmd,out="Arb.txt")

fo = open("Arb.txt", "r+")
line = fo.read(10)
print ("Read Line: %s" % (line))
if line == "true":
cmd="http://apache:8080/api/set/11131/?value=0"
filename = wget.download(cmd,out="switch.txt")
os.remove("switch.txt")

else:
cmd="http://apache:8080/api/set/11131/?value=1"
filename = wget.download(cmd,out="switch.txt")
os.remove("switch.txt")
fo.close()
os.remove("Arb.txt")
</SNIP>

Kann ich in Python ( Aktuelle Version Python 3.8.2) wget nicht so "umbiegen", das ich keine datei schreibe?

Wie gesagt, das sind meine ersten Gehversuche, und ich will das sauber machen.. Datei auf platte schreiben-> Datei zum lesen Öffnen-> dann löschen ist nicht die feine Art meine ich.

Ich hoffe das Ihr alle Gesund seid, und bin für Alle Infos dankbar.

Jörg
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das hat mit Python nichts zu tun, wget will Dinge ins Dateisystem legen. Das ist dem auch nur sehr schwer abzugewoehnen, und bisher habe ich das nur mit Umlenkung nach /dev/null gemacht. Da ist es aber natuerlich etwas nutzlos. Edit: ich sehe gerade, du machst das ja auch -O. Das geht theoretisch, wuerde ich aber nicht machen. Sondern:

Aber in Python wuerde man eh wget (oder curl) nicht benutzen. Sondern einfach das requests Modul benutzen. Musst du ggf. vorher installieren. Und als Konsequenz hast du uA auch deine Rueckgabe im Speicher, statt auf Platte.

Und fuer Arbeit mit Dateien benutzt man die "rohen" os-calls heutzutage nicht, sondern bemueht die "pathlib".
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Benutze statt <snip> Code-Tags, dann ist der Code hier im Forum auch lesbar. r+ ist als Dateimodus nie sinnvoll. Lesezugriff hellt man mit "r". Der if- und else-Block unterscheiden sich nur in einem Zeichen. Da benutzt man also eine Variable. HTTP liest man entweder mir dem eingebauten urllib-Modul oder requests.
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Wenn es unbedingt wget sein soll, geht es neben '-O -' vielleicht mit Fifos/Named Pipes. Das ist aber auch ganz schönes Gebastel (habe es nicht ausprobiert); ich würde das nicht empfehlen. Oder nimm curl, das schreibt doch eh auf stdout, wenn ich mich nicht vertute. Der beste Weg wäre aber eine reine Python-Lösung, zum Beispiel mit Requests.
joerg-harrer
User
Beiträge: 2
Registriert: Samstag 2. Mai 2020, 11:52

Danke für Eure Antowot. ja, noch viel zu lernen ....
Habe jetzt requests zum laufen gebracht

Code: Alles auswählen

def toggle_ARb():
     cmd = "http://apache:8080/api/getPlainValue/11131"
     r = requests.get(cmd)   

     if r.content.decode() == "true":
          cmd="http://apache:8080/api/set/11131/?value=0"
          r = requests.get(cmd)  
     else:
          cmd="http://apache:8080/api/set/11131/?value=1"
          r = requests.get(cmd)  
gefäät mir schon besser.
Danke für Eure Hilfe.
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Mal als Proof-of-Concept:

Code: Alles auswählen

#!/usr/bin/env python3
import os
import tempfile
import subprocess
import pathlib
import shutil
WGET_PATH = shutil.which('wget')


def download_file(url, fifo_name='fifo', wget_path=WGET_PATH):
    if wget_path is None:
        raise RuntimeError('No wget path.')
    result = None
    with tempfile.TemporaryDirectory() as directory:
        fifo = pathlib.Path(directory) / fifo_name
        os.mkfifo(fifo)
        with subprocess.Popen([wget_path, url, '-O', fifo]) as process:
            with fifo.open('r') as fh:
                result = fh.read()
    return result


def main():
    file = download_file('http://127.0.0.1/largefile')
    print(len(file))


if __name__ == '__main__':
    main()
Das müsste man natürlich noch deutlich robuster machen, wenn man das verwenden wollen würde (was man eh nicht wollen würde ;) ). Ich wollte nur mal wissen, ob das prinzipiell wirklich klappen würde.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Eingerückt wird immer mit 4 Leerzeichen pro Ebene nicht 5.
HTTP-Antworten haben ihr eigenes Encoding, das response.text auch berücksichtigt. Mit dem Default-Encoding von Python den Text zu decodieren ist also falsch.
Wie ich schon geschrieben hatte, sind der if-Block und der else-Block fast identisch, sollten also gar nicht existieren.
Statt drei mal die fast selbe URL im Code stehen zu haben, sollte man diese auch einmal als Konstante definieren.
Benutze keine Abkürzungen. Was soll den ARb sein? r ist ein response. Womöglich gar json-codiert?

Code: Alles auswählen

API_URL = "http://apache:8080/api"

def toggle_ARb(value_id=11131):
    cmd = "getPlainValue/11131"
    response = requests.get(f"{API_URL}/getPlainValue/{value_id}")   
    new_value = 0 if response.json() else 1
    # oder doch response.text == "true"?
    response = requests.get(f"{API_URL}/set/{value_id}", params={"value": new_value})
    response.raise_for_status()
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@joerg-harrer: Der Bash-Quelltext sieht ziemlich wüst aus was die Einrückung angeht.

Das sieht auch falsch aus denn im Skript steht bereits ``wget`` in `$cmd` steht es dann aber *noch mal*. Und damit ist es auch nicht mehr wirklich ein `$cmd` sondern eher eine `$url`.

Für das ``if``/``else`` gilt das gleiche was Sirius3 für das erste Python-Programm gesagt hat: Die unterscheiden sich nur durch ein einzelnes Zeichen.

Sähe dann eher so aus:

Code: Alles auswählen

readonly API_URL='http://apache:8080/api'
readonly SOME_MAGIC_NUMBER='11131'

if [[ "$(wget -q -O - "$API_URL/getPlainValue/$SOME_MAGIC_NUMBER")" == 'true' ]]; then
    value=0
else 
    value=1
fi
x=$(wget -q -O - "$API_URL/set/$SOME_MAGIC_NUMBER/?value=$value") 2&> /dev/null
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten