Labeldruck und was draus folgt

Du hast eine Idee für ein Projekt?
theoS
User
Beiträge: 108
Registriert: Dienstag 5. November 2019, 21:44

Mittwoch 25. März 2020, 22:19

Hab nun Zeit gehabt, den Code durchzuschauen. So ganz erschließt sich der Vorteil von map() für mich nicht. Hab gelesen, dass das elegant sein soll, aber den Vorteil daraus? Ist für mich eher verwirrend als logisch.
Aber egal, das funktioniert, und da es elegant sein soll, warum nicht? Wieder was neues kennengelernt.

Den Logger heb ich mir für später auf, der ist mir ein wenig zu redselig. Ich brauch ja nur immer das Zwischenergbnis für mich, dass ich weiß was der Code da tut.
Aber ich sehe schon, dass das noch nützlich werden kann...
Danke für die Tipps!
Den Teil des Codes habe ich nun in mein USB-Überwachungsteil eingebaut, das jetzt so wie ich es jetzt hab, die beiden Dateiinhalte austauscht, wie es das soll.
Gibt bestimmt was zu verbessern. :o)

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from pathlib import Path
import pyudev
import time
import pathlib
from datetime import datetime as DateTime
###---------------------------------------------------
PFAD = Path.home() / ".DruckData"
##ABFRAGE_FILENAME = PFAD / "TB_Ausgabe_Abfrage8StueckII.txt"
##ZAEHLER_FILENAME = PFAD / "numbers.csv"
###----------------------------------------------------
MEDIA_PFAD = Path('/media/earl/')
WECHSEL_DATEI_NAMEN = ["numbers.csv", "TB_Ausgabe_8iii.txt"]
print(MEDIA_PFAD)
context = pyudev.Context()
def usb_ansteckerkenner():
    monitor = pyudev.Monitor.from_netlink(context)
    monitor.filter_by('block')
    for device in iter(monitor.poll, None):
        if 'ID_FS_TYPE' in device: ###
            
            print(device.action)
            if device.action == 'add':
                
                name_of_stick = Path(device.get('ID_FS_LABEL'))
                print(name_of_stick)
                time.sleep(2)
                
                return name_of_stick
           
####--------------------------------------------------------------------#####

def copy(source_path, destination_path):    
    try:
        text = source_path.read_text(encoding="utf-8")        
        destination_path.write_text(text, encoding="utf-8")
    except FileNotFoundError as error:
        print(error)
           
####--------------------------------------------------------------------#####

def datei_auf_stick(name_of_stick, dateipfad, timestamp):    
    copy(
        PFAD / dateipfad,
        MEDIA_PFAD
        / name_of_stick
        / dateipfad.with_name(
            f"{dateipfad.stem}_{timestamp:%Y-%m-%d_%H_%M}.csv"
        ),
    )
           
####--------------------------------------------------------------------#####

def datei_auf_arbeitsverzeichnis(name_of_stick, dateipfad):
    copy(MEDIA_PFAD / name_of_stick / dateipfad, PFAD / dateipfad)

           
####--------------------------------------------------------------------#####

def main():
    timestamp = DateTime.now()
    name_of_stick = usb_ansteckerkenner()
    
    for dateiname in map(Path, WECHSEL_DATEI_NAMEN):  
        datei_auf_stick(name_of_stick, dateiname, timestamp)
        datei_auf_arbeitsverzeichnis(name_of_stick, dateiname)
    

if __name__ == "__main__":
    main()        
Nächster Schritt: Fehlerabfangen...
Wenn die Datei nicht da ist, soll da eine kleine Box aufgehen, die knapp drüber informiert, dass da mit den Dateien was nicht passt.
Die Box soll über den Knöpfen des anderen Codeteils liegen und nichts anderes machen als den stick zu unmounten.
Grübel...
Sirius3
User
Beiträge: 12392
Registriert: Sonntag 21. Oktober 2012, 17:20

Mittwoch 25. März 2020, 22:33

Da hat es jetzt noch so Zeilen mit vielen Minuszeichen, die den Lesefluß stören. Funktionen trennt man mit zwei Leerzeilen.
theoS
User
Beiträge: 108
Registriert: Dienstag 5. November 2019, 21:44

Mittwoch 25. März 2020, 22:34

Danke, die kommen noch raus, das brauch ich im Moment noch um die Trennung zu sehen.
Bin schon ein alter Mann :)
theoS
User
Beiträge: 108
Registriert: Dienstag 5. November 2019, 21:44

Mittwoch 25. März 2020, 22:59

Zum Auswerfen des Sticks kann ich so was verwenden.

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from pathlib import Path
import subprocess

MEDIA_PFAD = Path("/media/earl/")
def main():
    vpath = MEDIA_PFAD  / "SEAGULL"
    print(vpath)
    cmd = 'umount ' + str(vpath)
    print(cmd)
    subprocess.Popen(str(cmd), shell=True, stdout=subprocess.PIPE)

if __name__ == "__main__":
    main() 
wobei mich da irritiert, dass ich das Path-Objekt in einen String umwandeln muss, aber das muss wohl so sein weil ich das ja an die Shell durchreiche.
Gibts da noch was besseres?
__deets__
User
Beiträge: 8404
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 25. März 2020, 23:23

Ja, subprocess ohne Shell=True und mit einer Liste statt einem String - dann muss auch kein path konvertiert werden.
Sirius3
User
Beiträge: 12392
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 26. März 2020, 08:32

statt `Popen` benutzt man `run` und statt `shell=True` eine Liste.

Code: Alles auswählen

MEDIA_PFAD = Path("/media/earl/")

def main():
    umount_result = subprocess.run(["umount", MEDIA_PFAD / "SEAGULL"], check=True, stdout=subprocess.PIPE)
    print(umount_result.stdout)

if __name__ == "__main__":
    main()
theoS
User
Beiträge: 108
Registriert: Dienstag 5. November 2019, 21:44

Donnerstag 26. März 2020, 20:22

OK, danke. Das funktioniert.
Hab das jetzt in die USB-Ansteckgeschichte oben eingebaut, der Stick wir ausgehängt, allerdings stoppt dann das ganze Programm. Klar, krieg ich hier eine Fehlermeldung weil die Datei nicht da ist, aber das Programm stoppt jetzt auch bei Erfolg.
Das ist doof.
Muss man das so machen wie bei der tkinter-Oberfläche? mit root.mainloop()?
Dann würde das funktionieren wenn ich die Teile dann mit der grafischen Oberfläche vereine?

Dann noch eine Frage.
Bin von VBA das so gewohnt, dass wenn ich eine Variable hab, die ich so oft in gleicher Weise brauch wie hier den name_of_stick, dann deklariere ich den Global und kann dann in jedem Modul drauf zugreifen. Soll schlechter Stil sein, aber wäre das hier nicht geschickter als die x Übergaben? (man wird in VBA zum Faulpelz erzogen...)

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from pathlib import Path
import pyudev
import time
#import pathlib
from datetime import datetime as DateTime
import subprocess

PFAD = Path.home() / ".DruckData"
###----wird später gebraucht------
##ABFRAGE_FILENAME = PFAD / "TB_Ausgabe_Abfrage8StueckII.txt"
##ZAEHLER_FILENAME = PFAD / "numbers.csv"
###------------------------------

MEDIA_PFAD = Path('/media/earl/')
WECHSEL_DATEI_NAMEN = ["numbers.csv", "TB_Ausgabe_8iii.txt"]
print(MEDIA_PFAD)
context = pyudev.Context()
def usb_ansteckerkenner():
    monitor = pyudev.Monitor.from_netlink(context)
    monitor.filter_by('block')
    for device in iter(monitor.poll, None):
        if 'ID_FS_TYPE' in device: ###
            
            print(device.action)
            if device.action == 'add':
                
                name_of_stick = Path(device.get('ID_FS_LABEL'))
                print(name_of_stick)
                time.sleep(2)
                
                return name_of_stick
           

def copy(name_of_stick, source_path, destination_path ):    
    try:
        text = source_path.read_text(encoding="utf-8")        
        destination_path.write_text(text, encoding="utf-8")
    except FileNotFoundError as error:
        rauswerfer(name_of_stick)
        print(error)
           

def datei_auf_stick(name_of_stick, dateipfad, timestamp):    
    copy(name_of_stick,   
        PFAD / dateipfad,
        MEDIA_PFAD
        / name_of_stick
        / dateipfad.with_name(
            f"{dateipfad.stem}_{timestamp:%Y-%m-%d_%H_%M}.csv"
        ),
                
    )
           

def datei_auf_arbeitsverzeichnis(name_of_stick, dateipfad):
    copy(name_of_stick, MEDIA_PFAD / name_of_stick / dateipfad, PFAD / dateipfad)

  
def rauswerfer(name_of_stick):
    print(name_of_stick)
    umount_result = subprocess.run(["umount", MEDIA_PFAD / name_of_stick], check=True, stdout=subprocess.PIPE)
    print(umount_result.stdout)
         

def main():
    timestamp = DateTime.now()
    name_of_stick = usb_ansteckerkenner()
    
    for dateiname in map(Path, WECHSEL_DATEI_NAMEN):  
        datei_auf_stick(name_of_stick, dateiname, timestamp)
        datei_auf_arbeitsverzeichnis(name_of_stick, dateiname)
    

if __name__ == "__main__":
    main()        
theoS
User
Beiträge: 108
Registriert: Dienstag 5. November 2019, 21:44

Sonntag 29. März 2020, 11:14

Gut, ich habe jetzt mal was probiert, das scheint zu funktionieren.
Dachte mir, wenn das dann in der Fehlerbehandlung abbricht, rufe ich einfach die main() noch mal auf, dann läuft die wieder...
Also meinen "rauswerfer" eine Zeile dazu.

Code: Alles auswählen

def rauswerfer(name_of_stick):
    print(name_of_stick)
    umount_result = subprocess.run(["umount", MEDIA_PFAD / name_of_stick], check=True, stdout=subprocess.PIPE)
    print(umount_result.stdout)
    main()
Das geht, aber ob das so gut ist?
Sirius3
User
Beiträge: 12392
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 29. März 2020, 11:30

Das ist nicht gut. Ich weiß auch gar nicht genau, was denn Dein Problem mit dem Code oben ist. Du hast gar keine Schleife, also kann das auch nicht dauerhaft laufen.
theoS
User
Beiträge: 108
Registriert: Dienstag 5. November 2019, 21:44

Sonntag 29. März 2020, 11:54

Das läuft sonst weiter, wenn kein Fehler auftritt. Die Überwachung des USB läuft auch wenn das kopieren klappt. Nur wenn ein Fehler auftritt geht das nicht mehr weiter. Wenn ich main aufrufe danach geht's weiter
__deets__
User
Beiträge: 8404
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sonntag 29. März 2020, 11:59

Das ist wirklich wirklich nicht richtig. main sollte genau *einmal* aufgerufen werden. Und in main sollten Dinge stehen, die man auch garantiert nur einmal machen will und kann. Wenn nicht, dann hast du da noch Code an anderen Stellen rumfliegen, wo er nicht hingehoert. Edit: (Wie waere es mal mit einem Gesamtbild, nicht nur Ausschnitten?) - hast du ja geliefert, ich schaue mir das mal an.
__deets__
User
Beiträge: 8404
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sonntag 29. März 2020, 12:04

So, das ist ja auch kein Wunder, dass main wieder aufrufen das Problem loest. Man muss etwas, dass man andauernd machen will, auch andauernd machen. Nicht nur einmal, und sich dann rekursiv selbst aufrufen. So in etwa:

Code: Alles auswählen

from pathlib import Path
import pyudev
import time
#import pathlib
from datetime import datetime as DateTime
import subprocess

PFAD = Path.home() / ".DruckData"
###----wird später gebraucht------
##ABFRAGE_FILENAME = PFAD / "TB_Ausgabe_Abfrage8StueckII.txt"
##ZAEHLER_FILENAME = PFAD / "numbers.csv"
###------------------------------

MEDIA_PFAD = Path('/media/earl/')
WECHSEL_DATEI_NAMEN = ["numbers.csv", "TB_Ausgabe_8iii.txt"]
print(MEDIA_PFAD)


def usb_ansteckerkenner(context):
    monitor = pyudev.Monitor.from_netlink(context)
    monitor.filter_by('block')
    for device in iter(monitor.poll, None):
        if 'ID_FS_TYPE' in device:  ###

            print(device.action)
            if device.action == 'add':

                name_of_stick = Path(device.get('ID_FS_LABEL'))
                print(name_of_stick)
                time.sleep(2)

                return name_of_stick


def copy(name_of_stick, source_path, destination_path ):
    try:
        text = source_path.read_text(encoding="utf-8")
        destination_path.write_text(text, encoding="utf-8")
    except FileNotFoundError as error:
        rauswerfer(name_of_stick)
        print(error)


def datei_auf_stick(name_of_stick, dateipfad, timestamp):
    copy(name_of_stick,
        PFAD / dateipfad,
        MEDIA_PFAD
        / name_of_stick
        / dateipfad.with_name(
            f"{dateipfad.stem}_{timestamp:%Y-%m-%d_%H_%M}.csv"
        ),

    )


def datei_auf_arbeitsverzeichnis(name_of_stick, dateipfad):
    copy(name_of_stick, MEDIA_PFAD / name_of_stick / dateipfad, PFAD / dateipfad)


def rauswerfer(name_of_stick):
    print(name_of_stick)
    umount_result = subprocess.run(["umount", MEDIA_PFAD / name_of_stick], check=True, stdout=subprocess.PIPE)
    print(umount_result.stdout)


def main():
    context = pyudev.Context()

    while True:
        timestamp = DateTime.now()
        name_of_stick = usb_ansteckerkenner(context)

        for dateiname in map(Path, WECHSEL_DATEI_NAMEN):
            datei_auf_stick(name_of_stick, dateiname, timestamp)
            datei_auf_arbeitsverzeichnis(name_of_stick, dateiname)


if __name__ == "__main__":
    main()
theoS
User
Beiträge: 108
Registriert: Dienstag 5. November 2019, 21:44

Sonntag 29. März 2020, 13:06

Muss ich mal ausprobieren. Komisch ist dann aber, dass das mit dem überwachen vom USB port funktioniert. Das läuft weiter wenn ich den Stick einstecke und auswerfe, wird mir das beim nächsten Einstecken wieder angezeigt. Das läuft also doch weiter, sonst würde das doch nur einmal angezeigt.
Das mit der Schleife ist sicher sicherer, oder? Also lag ich mit meiner Annahme so “eine Art root.mainloop()“ gar nicht so verkehrt.
__deets__
User
Beiträge: 8404
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sonntag 29. März 2020, 13:24

Was du mit dem weiterlaufen meinst weiss ich nicht. Bezueglich des "sicherer" - jein. Es ist richtiger. Oder besser "nicht falsch". Denn man benutzt in Python keine Rekursion fuer Schleifen, und vor allem ist der Programmfluss bei deiner "Loesung" kompletter Wahnsinn, und nie wieder zu verstehen. Falls man ihn je verstanden hat.
theoS
User
Beiträge: 108
Registriert: Dienstag 5. November 2019, 21:44

Sonntag 29. März 2020, 13:36

Mit weiter laufen meine ich, dass das Progg immer erkennt ob ein Stick eingesteckt wird oder nicht.
Wenn die Dateien dann da sind, klappt das hin und herkopieren einwandfrei. Vereinfacht, wenn ich mir nur die Aktion anzeigen lasse, kann ich den Stick 100 mal rein und wieder rausmachen, es wird immer die Aktion angezeigt.
Daraus schließe ich nach wie vor, dass das Programm “weiterläuft“.
Da es stoppt, wenn ein Fehler kommt bin ich halt auf die Idee gekommenen das Ganze neu zu starten. Für mich ist das schon logisch, ahnte aber dass das sicher wieder nicht pythonlike ist.
Oder wo anders Murks erzeugt.
Antworten