Diverse Fragen zu verschiedenenen Problemen

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
Bl3nder
User
Beiträge: 139
Registriert: Freitag 3. Januar 2020, 17:07

Schönen guten Tag Ich hätte ein paar Fragen zu verschiedenenen Anwendungfällen ( Ich würde da gerne eine zweite Meinung zu hören)



Fall 1 :

Ich habe an einem anderen Speicherort Datein die Ich in einem anderen Ordner kopieren möchte jedoch kann es sein das die Datei vorhanden ist aber auf einem anderen stand daher wird in dem Fall die größe der Dateien ermittelt:

Frage kann Ich mir das shutil.copy(str(wetterstation_datei), str(datenbestand_datei)) unter der if Abfrage sparen und einfach raise FileNotFoundError dahin schreiben da in dem Fall
ja genau die gleichen Befehle dort ausgeführt werden ... da man sich ja nicht wiederholen soll?

Code: Alles auswählen

    for file in os.listdir(PFAD_WETTERSTATION):
        wetterstation_datei = os.path.join(PFAD_WETTERSTATION, file)
        datenbestand_datei = os.path.join(datenbestand_pfad, file)
        try:
            if os.path.getsize(wetterstation_datei) != os.path.getsize(datenbestand_datei):
                shutil.copy(str(wetterstation_datei), str(datenbestand_datei))  
        except FileNotFoundError:
            shutil.copy(str(wetterstation_datei),str(datenbestand_datei))


Fall 2:

Ich habe möchte eine Excel Datei bearbeiten die bereits offen ist was in der Regel zu einer Exception führen würden.Mein Gedanke ist nun folgender Ich möchte das mein Programm ohne eine interaktion des Nutzers auskommt und möchte die Datei schließen und erneut versuchen die Datei zu bearbeiten.

Frage was haltet ihr von so einer Lösung?

Code: Alles auswählen

import os
import pandas as pd
from win32com.client import Dispatch
 
 
def messdaten_in_datenbank(file, messdaten_ueberarbeitet):
    """
    Die überarbeitetenden Daten werden wieder in die Datei geschrieben
    Sorgt dafür das kein neues Arbeitsblatt erschaffen wird:
    writer.sheets = {sheet.title: sheet for sheet in writer.book}
    :param file: Pfad zu den Datein
    :param messdaten_ueberarbeitet:Daten mit NaN
    :return:
    """
    versuche = 3
    for zaehler in range(versuche):
        try:
            sheetname = str(os.path.basename(file)).split(".")[0]
            with pd.ExcelWriter(file, engine="openpyxl", mode="a") as writer:
                writer.sheets = {sheet.title: sheet for sheet in writer.book}
                messdaten_ueberarbeitet.to_excel(writer,
                                                 sheet_name=sheetname,
                                                 startrow=2,
                                                 startcol=4,
                                                 header=None,
                                                 index=None,
                                                 float_format="%.1f")
        except PermissionError:
            if zaehler < versuche - 1:
                print(f"{file} ist noch geöffnet einen Augenblick bitte!")
                excel_datei_schliessen()
                continue
            else:
                raise
        break
 
 
def excel_datei_schliessen():
    excel = Dispatch("Excel.Application")
    excel.Visible = False
    excel.DisplayAlerts = False
    workbook = excel.Workbooks
    workbook.Close()
    excel.Quit()
def main():
    messdaten_in_datenbank(file="test.xlsx", messdaten_ueberarbeitet=pd.Series(1, 2, 3))
if __name__ == "__main__":
    main()


Fall 3:

Was haltet ihr von verschachtelten try -except Blöcken und warum sollte man diese nicht verwenden ?

Code: Alles auswählen

import xlrd
import pandas as pd
import sys
 
 
neue_daten_pfad = (r"C:\Users\Marcel\PycharmProjects\Marcel Klimastatistik\Datenbestand\KLIMA16.XLS")
 
def test(pfad):
 
    #neue_daten = "Test"
    try :
        #1ter Versuch
        try:
            neue_daten = pd.read_excel(
                pfad,
                sheet_name="Mai",
                skiprows=8
                )
            return neue_daten
        except xlrd.biffh.XLRDError:
            print("Mai ist nicht vorhanden es wird nun mit einem Leerzeichen versucht!")
        #2ter Versuch
        try:
            neue_daten = pd.read_excel(
                pfad,
                sheet_name="Mai ",
                skiprows=8
                )
            return neue_daten
        except xlrd.biffh.XLRDError:
            raise
    except:
        print("Leider nicht vorhanden")
        sys.exit(-1)
test(neue_daten_pfad)


Ich freue mich auf eure Antworten
Eine Vision ohne Aktion bleibe eine Illusion
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Bl3nder: Wäre IMHO ein Hack weil es die Datei dann ja gibt und ein `FileNotFound` irreführend ist. Ich würde ein Flag setzen und danach erst kopieren. Und `pathlib` statt `os.path` verwenden.

Du testest gar nicht ob es sich überhaupt um eine Datei handelt.

Namen die auf `*_datei` enden aber gar nicht für Dateiobjekte sondern Dateinamen oder -pfade stehen sind verwirrend.

Ungetestet:

Code: Alles auswählen

    for wetterstation_datei_pfad in WETTERSTATION_PFAD.iterdir():
        if wetterstation_datei_pfad.is_file():
            datenbestand_datei_pfad = (
                datenbestand_pfad / wetterstation_datei_pfad.name
            )
            try:
                need_copy = (
                    wetterstation_datei_pfad.stat().st_size
                    != datenbestand_datei_pfad.stat().st_size
                )
            except FileNotFoundError:
                need_copy = True

            if need_copy:
                shutil.copy(wetterstation_datei_pfad, datenbestand_datei_pfad)
Auch im Fall 2 ist `file` ein ungünstiger Name für etwas das gar kein Dateiobjekt ist.

`messdaten_in_datenbank` ist keine Tätigkeit, also kein guter Name für die Funktion. Eine Datenbank sehe ich da auch nicht.

Der Programmfluss ist IMHO ziemlich verwirrend mit dem extra Test und dem ``continue`` und dem ``raise`` im ``except``.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
from pathlib import Path

import pandas as pd
from win32com.client import Dispatch


def excel_datei_schliessen():
    excel = Dispatch("Excel.Application")
    excel.Visible = False
    excel.DisplayAlerts = False
    excel.Workbooks.Close()
    excel.Quit()


def speichere_messdaten(file_path, ueberarbeitete_messdaten):
    """
    Die überarbeitetenden Daten werden wieder in die Datei geschrieben.

    :param file_path: Pfad zu den Dateien
    :param ueberarbeitete_messdaten: Daten mit NaN
    """
    exception = None
    for _ in range(3):
        try:
            with pd.ExcelWriter(
                file_path, engine="openpyxl", mode="a"
            ) as writer:
                writer.sheets = {sheet.title: sheet for sheet in writer.book}
                ueberarbeitete_messdaten.to_excel(
                    writer,
                    sheet_name=file_path.stem,
                    startrow=2,
                    startcol=4,
                    header=None,
                    index=None,
                    float_format="%.1f",
                )
        except PermissionError as error:
            exception = error
            print(f"{file_path} ist noch geöffnet einen Augenblick bitte!")
            excel_datei_schliessen()
        else:
            break
    else:
        raise exception


def main():
    speichere_messdaten(Path("test.xlsx"), pd.Series(1, 2, 3))


if __name__ == "__main__":
    main()
Das verschachteln in Fall 3 ist a) unsinnig wenn doch im zweiten inneren ``except`` bloss ein ``raise`` steht. Und es ist gefährlich weil das äussere ``except`` *alles* behandelt, auch Ausnahmen mit denen Du gar nicht rechnest.

Die beiden Versuche unterscheiden sich auch nur durch den Namen des Arbeitsblattes. Da sollte nicht zweimal fast der gleiche Code stehen.

Eine Funktion die Daten lädt sollte den Prozess nicht beenden sondern eine Ausnahme auslösen. `sys.exit()` gehört nur ins Hauptprogramm.

Negative Zahlen bei `sys.exit()` sind ein Fehler. Das sind positive ganze Zahlen zwischen 0 und 255, wobei einige davon auf bestimmten Betriebsystemen für die Shell(s) auch noch eine besondere Bedeutung haben.

Wieder ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import sys
from pathlib import Path

import pandas as pd
import xlrd

NEUE_DATEN_PFAD = Path(
    R"C:\Users\Marcel\PycharmProjects\Marcel Klimastatistik\Datenbestand",
    "KLIMA16.XLS",
)


def test(pfad):
    for suffix in ["", " "]:
        try:
            return pd.read_excel(pfad, sheet_name="Mai" + suffix, skiprows=8)
        except xlrd.biffh.XLRDError:
            pass

    raise ValueError("no appropriate sheet name found")


def main():
    try:
        print(test(NEUE_DATEN_PFAD))
    except ValueError:
        sys.exit("Leider nicht vorhanden")


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Bl3nder
User
Beiträge: 139
Registriert: Freitag 3. Januar 2020, 17:07

]Ich danke dir erstmal für die vielen Vorschläge,jedoch habe Ich eine kurze frage zu sys.exit():

Ich habe leider keine direkte bedeutung der Zahlen gefunden deswegen beziehe Ich mich mal auf ein alte Bibliothek:


EXIT STATUS
Wget may return one of several error codes if it encounters problems.

0 No problems occurred.

1 Generic error code.

2 Parse error---for instance, when parsing command-line options, the .wgetrc or .netrc...

3 File I/O error.

4 Network failure.

5 SSL verification failure.

6 Username/password authentication failure.

7 Protocol errors.

8 Server issued an error response.


Unter Windows ist der exit code eine 32 Bit Zahl sprich 4294967295 ,Ich habe eine alte Tabelle dazu gefunden http://www.hiteksoftware.com/knowledge/articles/049.htm

Wie man sieht unterscheiden sich die Bibliothek und die Dokumentation von ein ander sollte man also die Zahl selber wählen oder es diese in Python irgendwo genormt oder sollte man sich an das OS halten.

Wichtige Anmerkung:

Ich frage deswegen da Ich das "Skript/Programm" mit dem Aufgabenplaner aufrufen möchte wenn das Programm erfolgreich ausgeführt wurde steht dort dann ja
"Der Vorgang wurde erfolgreich beendet (0x0)" mal angenommen Ich übergebe nun eine andere Zahl zum Beispiel 2 ändert das irgendwas ? Also in der Vergangenheit meine Ich das -1 ebenfalls akzeptiert wurde und dann wurde später nochmal versucht die Datei zu start. Und wieso sollte man -1 nicht übergeben bzw ist diese -1 eigentlich für andere Betriebssysteme ? Ich danke euch
Eine Vision ohne Aktion bleibe eine Illusion
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Bl3nder: Es gibt nicht *die* Bedeutung der Zahlen. Es gibt verschiedene Betriebssysteme und verschiedene Versuche irgendwelche Standards zu etablieren. Unter Linux ist das Argument von `exit()` zwar auch ein `int` aber das wird mit 0xff bitweise Und-verknüpft, dass heisst aus einer -1 wird 255. Man kann da also gar keine negativen Zahlen zurückgeben. Wenn man einfach nur zwischen erfolgreich oder nicht unterscheiden will, dann sind 0 (erfolgreich) und 1 (irgendein Problem) wohl am sichersten. Oder noch besser: kein Argument oder eine Zeichenkette die ausgegeben wird. Dann kümmert sich Python um passende Werte.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Bl3nder
User
Beiträge: 139
Registriert: Freitag 3. Januar 2020, 17:07

Ja jetzt habe Ich es verstanden -> wenn Ich sys.exit("Notfall") schreibe wird in Python daraus automatisch sys.exit(1) und gibt zusätzlich den Text aus.Ich danke dir Ich dachte man muss es explizit festlegen.
Eine Vision ohne Aktion bleibe eine Illusion
Antworten