Seite 1 von 1

Kann mal jemand über mein erstes "Programm" gucken?

Verfasst: Dienstag 8. Mai 2012, 19:57
von knapp
Hallo,

ich habe mein erstes Programm mit Python fertig.
Bevor ich es auf meine Festplatte loslasse, würde ich mich freuen, wenn sich das mal jemand von den Experten hier kurz ansehen würde, damit ich mir damit nicht meine Daten schreddere.

Das Programm soll alle Dateien (keine Verzeichnisse), die in einem festgelegten Verzeichnis liegen, in neue oder bestehende Ordner verschieben. Die Ordnernamen sollen dem Dateidatum im Format YYYY-MM-DD entsprechen.
Wenn etwas nicht stimmt, also z.B. eine Datei vorhanden ist, deren Name mit dem eines zu erstellenden Ordners übereinstimmt, dann soll das Programm einfach abbrechen.


Ich habe viele Printausgaben im Code, die ich zum Programmieren benötigt habe. Ich lasse diese im Code, weil sie helfen, diesen zu verstehen.

Code: Alles auswählen

import os, time, shutil

Verz1 = "./tmp"     # Sourceverzeichnis
Verz2 = "./tmp2"    # Zielverzeichnis
Verz_Funde = 0      # Anzahl der gefunden Verzeichnisse im Sourceverz.
Not_Aus = 0         # Sicherheitszähler


while len(os.listdir(Verz1)) > Verz_Funde:  # Solange mindestens eine Datei im Sourceverz. ist...
    Not_Aus = Not_Aus + 1
    if Not_Aus > 100:
        exit()

    Verz_Liste = os.listdir(Verz1)  # Liste aller Elemente im Sourceverzeichnis
    Laenge_Verz_Liste = len(Verz_Liste) 
    print ("Elemente im Verzeichnis:  " + str(Laenge_Verz_Liste))
    print ("Verz_Liste[Verz_Funde]: "  +  Verz_Liste[Verz_Funde])
    Element1 = os.listdir(Verz1)[Verz_Funde]
    print ("Element1: " + Element1)
    Pfad_Element1 = Verz1 + "/" + Element1
    print ("ganzer Pfad: " + Pfad_Element1)
    if os.path.isdir(Pfad_Element1):    # wenn das Element ein Verz. ist,...
        Verz_Funde = Verz_Funde + 1     # ... dann setze den Zähler hoch, um das nächste Element zu nehmen
    else:
        Datum_Element1 = os.stat(Pfad_Element1)[9]
        Datum_Element1_Conv = time.strftime("%Y-%m-%d", time.gmtime(Datum_Element1))
        print ("Datum der Datei: " + Datum_Element1_Conv)

        N_Verz = Verz2 + "/" + Datum_Element1_Conv  # zu erstellendes Verzeichnis
        print ("Neues Verzeichnis: " + N_Verz)
        if not os.path.exists(N_Verz):
            print("Erstelle neues Verzeichnis: " + N_Verz)
            os.mkdir (N_Verz)
        else:
            print("Verzeichnis schon vorhanden!")
        if os.path.isdir(N_Verz):
            print(N_Verz + "  - ist ein Verzeichnis")
            Ziel = N_Verz + "/" + Element1 
            print("Verschiebe:  " + Pfad_Element1 + " --> " + Ziel)
            shutil.move(Pfad_Element1,Ziel)
        else:
            print(N_Verz + "  - ist kein Verzeichnis")
            print()
            print ( "Da stimmt was nicht!   ----    Bitte prüfen!")
            exit()
        print ("wird das noch geschrieben")
        print("................................................")
        print()
print()
print("Gefundene Verzeichnisse im Ausgangsordner:  " + str(Verz_Funde))

Re: Kann mal jemand über mein erstes "Programm" gucken?

Verfasst: Dienstag 8. Mai 2012, 20:15
von Hyperion
Also ich habe jetzt nicht en detail drüber geguckt, da ich denke, man sollte das komplette neu schreiben. Das klingt hart, aber ich begründe es mal:

- Du solltest Deinen Code mehr gliedern! Teile das doch in kleinere Teilaufgaben auf, die Du in Funktionen kapselst. Diese kannst Du auch viel leichter *separat* testen, ohne irgend einen Schaden zu riskieren.

- Baue nicht `os.walk` (für Python 3.x - das benutzt Du doch!?) nach. Das bietet Dir doch schon alles, was Du brauchst. Damit sollte sich die ganze Schleife und die Programmlogik deutlich vereinfachen lassen.

- Baue Pfade nicht per `+` zusammen. Dafür gibt es `os.path.join` - Du hast ja für andere Funktionalität auch auf die entsprechenden Module und Funktionen zurückgegriffen.

- Wähle bessere Namen! `N_Verz` ist einfach - sorry - Mist. `N` steht für `neu`? Oder was? Zudem scheinst Du ja Daten zu haben, die kein Verzeichnis repräsentieren, aber dennoch an diesen Namen gebunden sind. Also überdenke mal, welche Namen Du wirklich brauchst und wähle diese dann ruhig auch länger - oder greife auf Englisch zurück. Das ist idR. kompakter.

- Nummeriere *niemals* Namen. Wenn Du das tust, willst Du eigentlich eine Liste o.ä. verwenden. `Verz1` und `Verz2` sind dafür ein "gutes" schlechtes Beispiel. Du musst im Kommentar erst dokumentieren, was diese Namen bedeuten bzw. welches Objekt sich dahinter verbirgt. Wieso nicht `src_dir` und `dest_dir`... oder, da es eh um Verzeichnisse geht in dem Modul, `source` und `destination`?

- Bitte beachte PEP8.

- Um das ganze wirklich benutzbar zu machen, schau Dir mal das `argparse`-Modul an. Damit kannst Du ganz einfach das Quell- und Zielverzeichnis per Kommandozeilenparameter übergeben. Imho ist das deutlich komfortabler, als das im Code anzupassen ;-)

- Anstelle `exit` zu nutzen, würde ich eine Exception werfen... oder zumindest `exit` einen Fehlercode mitgeben. Das gilt natürlich für Stellen, an denen ein Fehler auftritt.

- Gewöhne Dir schnell ab, Strings per `+` zu konkatenieren. Auch wenn das geht und Python es "erlaubt" ist das idR wenig performant und vor allem *schwer* lesbar. Nutze stattdessen `"".format` oder `"" % ()`.

So, ziemlich viel harter Tobak, aber ich hoffe es hilft Dir weiter :-)

Re: Kann mal jemand über mein erstes "Programm" gucken?

Verfasst: Dienstag 8. Mai 2012, 20:59
von knapp
Hyperion hat geschrieben:Also ich habe jetzt nicht en detail drüber geguckt, da ich denke, man sollte das komplette neu schreiben. Das klingt hart, aber ich begründe es mal:

- Du solltest Deinen Code mehr gliedern! Teile das doch in kleinere Teilaufgaben auf, die Du in Funktionen kapselst. Diese kannst Du auch viel leichter *separat* testen, ohne irgend einen Schaden zu riskieren.
Daran hatte ich auch gedacht, aber eigentlich macht das "Programm" ja fast gar nix. Wenn ich das in Funktionen aufteilen würde, dann würde das durch die Parameterübergabe auch nicht sehr übersichtlich werden.

Die vielen Prints machen es zudem sehr unübersichtlich. Wenn ich das Programm auf das Wesentliche reduzieren würde, sähe es sicher nicht so wild aus.
- Baue nicht `os.walk` (für Python 3.x - das benutzt Du doch!?) nach. Das bietet Dir doch schon alles, was Du brauchst. Damit sollte sich die ganze Schleife und die Programmlogik deutlich vereinfachen lassen.
Jau, ich benutzt Python 3.
Ich habe gerade mal nachgesehen, was os.walk macht. Kannte ich bisher nicht. Hab ja heute erst mit Python angefangen :-)
Mit os.walk könnte ich wohl eleganter die Dateien von den Verzeichnissen trennen.
- Baue Pfade nicht per `+` zusammen. Dafür gibt es `os.path.join` - Du hast ja für andere Funktionalität auch auf die entsprechenden Module und Funktionen zurückgegriffen.
OK, daran werde ich mich versuchen. Ich war erst mal froh, dass es mit "+" geklappt hat.
- Wähle bessere Namen! `N_Verz` ist einfach - sorry - Mist. `N` steht für `neu`? Oder was? Zudem scheinst Du ja Daten zu haben, die kein Verzeichnis repräsentieren, aber dennoch an diesen Namen gebunden sind. Also überdenke mal, welche Namen Du wirklich brauchst und wähle diese dann ruhig auch länger - oder greife auf Englisch zurück. Das ist idR. kompakter.
N_Verz beinhaltet das neu zu erstellende Verzeichnis. Ich frage nur noch ab, ob es schon existiert, oder ob vielleicht eine Datei mit dem gleichen Namen existiert. Aber grundsätzlich steht das für eine Verzeichnis.

Mit englischen Namen bin ich vorsichtig, weil ich damit unter VBA schon mal versehentlich reservierte Ausdrücke getroffen habe. Bei deutschen Namen kann das fast nicht passieren.

Die Variablennamen sind aber natürlich nicht toll. Das liegt aber auch daran, weil ich eben heute erst angefangen habe und mir alles zusammen suchen musste und vieles nur durch Ausprobieren herausgefunden habe.
Bei den ersten Tests war Verz1 noch keine Sourceverzeichnis.
- Bitte beachte PEP8.
Dieser knappe Satz hat es aber in sich, wie ich gerade sehe :-)

[/quote]- Um das ganze wirklich benutzbar zu machen, schau Dir mal das `argparse`-Modul an. Damit kannst Du ganz einfach das Quell- und Zielverzeichnis per Kommandozeilenparameter übergeben. Imho ist das deutlich komfortabler, als das im Code anzupassen ;-)[/quote]

Diese Option habe ich absichtlich weggelassen. Das Skript verschiebt die Daten ohne Rückfrage. Wenn ich da falsche Parameter angeben würde, könnte ich mir meine gesamte Festplatte umsortieren. Den Pfad lasse ich lieber fest im Skript.
- Gewöhne Dir schnell ab, Strings per `+` zu konkatenieren. Auch wenn das geht und Python es "erlaubt" ist das idR wenig performant und vor allem *schwer* lesbar. Nutze stattdessen `"".format` oder `"" % ()`.
OK, werde ich in Zukunft versuchen.
Die Performance ist für diese Anwendung hier nicht besonders wichtig. Ich möchte mit dem Skript nur relativ wenige Dateien verschieben, die mein Scanner erzeugt.
So, ziemlich viel harter Tobak, aber ich hoffe es hilft Dir weiter :-)
Auf jeden Fall. Danke.
Ein toller Programmierer werde ich sicher nicht werden, da ich immer nur mal so zwischendurch was für den Hausgebrauch mache, aber es schadet sicher nicht, wenn man wenigstens mal was von den Alternativen gehört hat.

Re: Kann mal jemand über mein erstes "Programm" gucken?

Verfasst: Dienstag 8. Mai 2012, 21:23
von Hyperion
Wenn jeder bezüglich der Generalisierung mittels Parameterübergabe so dächte wie Du, dann gäbe es wohl wenige Tools wie `ls`, `cp`, `find`, `grep` usw :-D

Zumindest könntest Du die Konfiguration in eine Datei auslagern - dann muss man wenigstens nicht direkt im Code etwas ändern und hätte ein wenig mehr Flexibilität. Python bietet dafür verschiedene Ansätze; von einem echten Python-Modul, welches Du simpel importierst, über Serialisierungsformate wie INI (`configparser`-Modul) oder JSON (`json`-Modul) usw.

Nebenbei böte sich eine Art "Dry-run"-Modus an; damit könntest Du erst einmal Einstellungen testen, bevor Du wirklich etwas verschiebst.

Re: Kann mal jemand über mein erstes "Programm" gucken?

Verfasst: Dienstag 8. Mai 2012, 22:20
von webspider
Hyperion hat geschrieben:Nebenbei böte sich eine Art "Dry-run"-Modus an; damit könntest Du erst einmal Einstellungen testen, bevor Du wirklich etwas verschiebst.
Bzw. ein Parameter wie "--force", der extra angegeben werden muss, damit auch tatsächlich verändert wird.

Re: Kann mal jemand über mein erstes "Programm" gucken?

Verfasst: Mittwoch 9. Mai 2012, 00:35
von BlackJack
@knapp: Das ist sehr ungünstig aufgebaut — um es mal vorsichtig auszudrücken. In der Bedingung ``while``-Schleife liest Du immer wieder alle Dateinamen aus dem Quellverzeichnis in eine Liste um dann im Schleifenkörper *noch einmal* alle Dateinamen aus dem Quellverzeichnis in eine Liste zu lesen um von der die Länge zu erfahren, um dann **noch einmal** alle Dateinamen aus dem Quellverzeichnis in eine Liste zu lesen, aus der dann *ein* Element verwendet wird. Argh. *So* verdammt viel unnötige Arbeit und dann insgesamt auch so undurchsichtig durch `Verz_Funde` als Index und Prüfkriterium mit dem nicht gerade offensichtlichen Zusammenspiel des Erhöhens von `Verz_Funde` wenn es ein Verzeichnis ist/war und dem Verschieben von Dateien was die andere Hälfte der ``while``-Bedingung beeinflusst.

Das Programm ist IMHO auch fehlerhaft, denn `os.listdir()` garantiert keine bestimmte oder feste Reihenfolge der Namen in der Liste. Auch nicht das bei jedem Aufruf die gleiche Reihenfolge geliefert wird. Insbesondere da Du das Quellverzeichnis durch das Verschieben von Dateien veränderst, könnte das auch eine Änderung der Reihenfolge der Namen bewirken. Das kommt ganz auf den Dateisystemtreiber und die dort verwendeten Datenstrukturen an.

Letztendlich, sofern ich in dem Gewirr nichts übersehen habe, möchtest Du doch nur alle Namen im Quellverzeichnis durchgehen und Verzeichnisse zählen und Dateien verschieben. Dazu muss man nur *einmal* `os.listdir()` aufrufen. Da bekommt man eine Liste mit allen Namen. Und darüber kann man mit einer ``for``-Schleife iterieren. Ganz einfach. Möchtest Du eigentlich Verzeichnisse wirklich zählen, oder ist das nur ein unnützes Nebenprodukt?

`Not_Aus` kann man durch „slicen” der ersten 100 Elemente von `os.listdir()` vermeiden. Entweder die Slice-Syntax oder mit `itertools.islice()`.

Die Elemente im `os.stat()`-Ergebnis sind auch über Attribute abrufbar. Das ist verständlicher als eine ”magische” 9 als Index.

Das Testen auf Verzeichnis kann man auch durch Ausnahmebehandlung lösen. Ich komme dann auf so etwas hier (ungetestet):

Code: Alles auswählen

import errno
import os
import shutil
from itertools import islice
from time import gmtime, strftime


def main():
    source = './tmp'
    destination = './tmp2'

    for name in islice(os.listdir(source), 100):
        source_path = os.path.join(source, name)
        if not os.path.isdir(source_path):
            date = strftime('%Y-%m-%d', gmtime(os.stat(source_path).st_ctime))
            destination_dir = os.path.join(destination, date)
            try:
                os.mkdir(destination_dir)
            except OSError, error:
                if error.errno != errno.EEXIST:
                    raise
            shutil.move(source_path, destination_dir)


if __name__ == '__main__':
    main()

Re: Kann mal jemand über mein erstes "Programm" gucken?

Verfasst: Mittwoch 9. Mai 2012, 10:28
von knapp
Ich sehe, ihr seid einhellig angetan von meinem "Programm" :)

BlackJack hat geschrieben:Letztendlich, sofern ich in dem Gewirr nichts übersehen habe, möchtest Du doch nur alle Namen im Quellverzeichnis durchgehen und Verzeichnisse zählen und Dateien verschieben. Dazu muss man nur *einmal* `os.listdir()` aufrufen. Da bekommt man eine Liste mit allen Namen. Und darüber kann man mit einer ``for``-Schleife iterieren. Ganz einfach. Möchtest Du eigentlich Verzeichnisse wirklich zählen, oder ist das nur ein unnützes Nebenprodukt?
Das Zählen der Verzeichnisse ist nur ein Nebenprodukt, welches vom Ausprobieren übrig geblieben ist.

Dass ich immer wieder das os.listdir() aufrufe, und dass das nicht ideal ist, hatte ich mir auch schon gedacht, aber grundsätzlich sollte es erst mal funktionieren.
Ich war mir nicht sicher, wie ich das Array, was os.listdir() vermutlich liefert, komplett in eine Variable bekomme. Aber das habe ich in meinem Programm ja schon mit #Verz_Liste = os.listdir(Verz1)# gemacht.

Bei durchschnittlich vielleicht 10 Elementen im Ordner wird ein Geschwindigkeitsvorteil sicher nicht auffallen :-)

Dein Argument, dass die Reihenfolge der Elemente in der Liste bei jedem Aufruf anders sein könnte, bekommt man nicht vom Tisch.
Das wäre zwar kein Problem, weil wenn eine Datei nicht kopiert werden würde, würde sie bei einer erneuten Ausführung des Programms kopiert werden, aber schön ist das natürlich nicht.
`Not_Aus` kann man durch „slicen” der ersten 100 Elemente von `os.listdir()` vermeiden. Entweder die Slice-Syntax oder mit `itertools.islice()`.
Da komme ich im Moment nicht mit.
Ich habe keine gescheite Erklärung gefunden, was itertools.islice() macht und wie man es einsetzt.
Die Elemente im `os.stat()`-Ergebnis sind auch über Attribute abrufbar. Das ist verständlicher als eine ”magische” 9 als Index.
Das ist eine Sache, um die ich mich gar nicht gekümmert hatte. Ich hatte zufällig genau diese Befehlszeile, die ich brauchte, per google gefunden und habe nicht dran rumgefummelt.
Das Testen auf Verzeichnis kann man auch durch Ausnahmebehandlung lösen. Ich komme dann auf so etwas hier (ungetestet):
Dieses "Try" wollte ich auch noch eingebaut haben, aber da hat mir dann die Zeit gefehlt.
Dein Code sieht natürlich sehr viel eleganter aus, als das Gewürge, was ich da fabriziert habe.

Eine Kleinigkeit fehlt bei dir aber vermutlich. Wenn zwei Elemente in der Liste das gleiche Datum haben, dann sollen die in den gleichen Ordner verschoben werden. Der Ordner kann auch schon vor dem Starten des Programms vorhanden sein. In deinem Programm würde mkdir() wahrscheinlich einen Fehler liefern und das Programm beenden.
Man müsste also noch eine Abfrage einbauen, ob das Verzeichnis schon vorhanden ist. Soweit ich das bisher gesehen habe, gibt es sowas wie DirExist() nicht. Deswegen bleibt vermutlich doch nur die Abfrage, ob das entsprechende Element existiert, und ob es ein Verzeichnis ist.

Code: Alles auswählen

import errno
            try:
                os.mkdir(destination_dir)
            except OSError, error:
                if error.errno != errno.EEXIST:
                    raise
            shutil.move(source_path, destination_dir)
    main()
Da bekomme ich einen Syntax-Error beim Komma hinter OSError angezeigt.

##################################
File "F:\z1\Datei_datum_2_02.py", line 31
except OSError, error:
^
SyntaxError: invalid syntax
##################################

Ich habe mal versucht mein Programm zu verbessern und mit euren Ratschlägen anzupassen.
Wenn ich mit die Pfade mit print() anzeigen lassen, dann bekomme ich jetzt mal Backslashes und mal Vorwärtsschräger (wie heißen die Shift + 7?). Das hängt vermutlich mit diesem os.path.join() zusammen.

Als ich die Pfad-Strings mit "+" zusammengefügt habe, wurde alles mit Vorwärtsschrägern angezeigt.
So, wie das jetzt angezeigt wird, habe ich Muffen, das tatsächlich laufen zu lassen.
Die Ausgabe in CMD unter XP sieht z.B. so aus:
#######################################
./tmp\myFile2.txt
Das Datum ist: 2012-05-08
erstelle Verz: ./tmp2\2012-05-08
Der Zielpfad ist: ./tmp2\2012-05-08\myFile2.txt
Kopiere: ./tmp\myFile2.txt -- > ./tmp2\2012-05-08\myFile2.txt
######################################

Mein Code sieht derzeit wie folgt aus. Die aktiven Teile habe ich auskommentiert, damit nicht auf der Platte geschrieben wird.
Die ganzen Prints sind nicht notwendig. Die dienen mir nur zur Kontrolle.

Code: Alles auswählen

import os, time, shutil, errno

Source_Dir = "./tmp"     # Sourceverzeichnis
Dest_Dir = "./tmp2"    # Zielverzeichnis

Verz_Liste = os.listdir(Source_Dir)  # Liste aller Elemente im Sourceverzeichnis

for Element in Verz_Liste:
    Source_Path_Compl = os.path.join(Source_Dir, Element)
    print (Source_Path_Compl)
    if not os.path.isdir(Source_Path_Compl):    # wenn das Element kein Verz. ist...
        Datum = time.strftime('%Y-%m-%d', time.gmtime(os.stat(Source_Path_Compl).st_ctime))
        print("Das Datum ist:  " + Datum)
        Dest_Dir_New = os.path.join(Dest_Dir, Datum)
        Dest_Path_Compl = os.path.join(Dest_Dir_New, Element)
        print ("erstelle Verz:      " + Dest_Dir_New)
        print ("Der Zielpfad ist:   " + Dest_Path_Compl)
        if not os.path.exists(Dest_Dir_New):
            try:
                print()
                #os.mkdir(Dest_Dir_New)
            except OSError:
                if error.errno != errno.EEXIST:
                    raise
        else:
            if not os.path.isdir(Dest_Dir_New):
                print()
                print("Da stimt was nicht   ----   Bitte prüfen!")
                exit()
            print ("Kopiere:    " +  Source_Path_Compl + " -- > " + Dest_Path_Compl)
            #shutil.move(Source_Path_Compl, Dest_Path_Compl)

Re: Kann mal jemand über mein erstes "Programm" gucken?

Verfasst: Mittwoch 9. Mai 2012, 11:24
von BlackJack
@knapp: Das mit dem ungünstigen Laufzeitverhalten fällt nicht auf, weil es auf 100 Schleifendurchläufe beschränkt ist. Denn sonst muss intern in den `os.listdir()`-Aufrufen insgesamt 3·n² mal ein Name an die jeweilige Ergebnisliste angehängt werden, mit `n` als Anzahl der Namen im Verzeichnis. Das wären bei 20 Namen 1.200, bei 100 Namen schon 30.000 und wenn man dann doch mal ein Verzeichnis mit 1.000 Namen hat 3 Millionen Operationen — *das* fällt dann vielleicht schon auf und ist um den Faktor 3.000 schlechter als es sein müsste. Mit der Beschränkung auf 100 Durchläufe sind es 300·n. Quadratische Laufzeiten sollte man jedenfalls vermeiden wenn es einfach vermeidbar ist.

`os.listdir()` liefert eine Liste. Steht in der Dokumentation, sowohl in der „externen”, als auch im DocString, und ausprobieren kann man das auch schnell in einer Python-Shell:

Code: Alles auswählen

In [59]: os.listdir?
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
String Form:    <built-in function listdir>
Namespace:      Interactive
Docstring:
    listdir(path) -> list_of_strings                                            
    
    Return a list containing the names of the entries in the directory.
    
            path: path of directory to list
    
    The list is in arbitrary order.  It does not include the special
    entries '.' and '..' even if they are present in the directory.


In [60]: os.listdir('tmp/sensors3')
Out[60]: ['chips.h', 'sensors.h', 'error.h']

In [61]: type(os.listdir('tmp/sensors3'))
Out[61]: <type 'list'>
Die ``?``-Syntax bei [59] ist IPython-spezifisch, da würde man in der normalen Python-Shell die `help()`-Funktion verwenden.

Array solltest Du das nicht nennen, denn es gibt in der Standardbibliothek und in der Numpy-Bibliothek Arrays als Datentypen.

Das `itertools`-Modul ist dokumentiert. Um die Beispiele und Dokumentation zu verstehen, ist es hilfreich die Slice-Syntax zu kennen. Das sind Grundlagen die ziemlich am Anfang vom Tutorial in der Python-Dokumentation erklärt werden. Das Tutorial sollte man mal durchgearbeitet haben um die Syntax und die eingebauten Datentypen kennen zu lernen.

Wenn ein Verzeichnis schon existiert, dann löst `os.mkdir()` einen `OSError` aus. Den behandle ich ja, also wird das Programm dadurch nicht beendet. Beziehungsweise nur wenn der `OSError` nicht durch das Vorhandensein des Verzeichnisses ausgelöst wurde. Es könnte ja noch andere Gründe geben, wie zum Beispiel fehlende Rechte.

Code: Alles auswählen

In [70]: os.mkdir('tmp')
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

OSError: [Errno 17] File exists: 'tmp'

In [71]: errno.errorcode[17]
Out[71]: 'EEXIST'

In [72]: errno.EEXIST
Out[72]: 17

In [73]: os.mkdir('/opt/tmp')
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

OSError: [Errno 13] Permission denied: '/opt/tmp'

In [74]: errno.errorcode[13]
Out[74]: 'EACCES'

In [75]: errno.EACCES
Out[75]: 13
Wenn man ein robustes Programm schreiben will, muss man sich um die entsprechende Ausnahme sowieso kümmern, da kann man sich einen extra Test ob ein Verzeichnis schon existiert an der Stelle sparen. Denn in `os.mkdir()` muss dieser Test ja auch eingebaut sein, sonst könnte keine Ausnahme ausgelöst werden, wenn das Verzeichnis schon existiert.

Der Syntaxfehler liegt daran, dass ich Python 2.x und Du 3.x verwendest. Da wird aus dem Komma ein Schlüsselwort: ``except OSError as error:``

Die Windows-API akzeptiert sowohl / als auch \ als Pfadtrenner. Nur die Shell kommt unter Windows nicht mit / klar, weil das unter DOS das Zeichen war mit dem man Optionen auf der Kommandozeile angegeben hat. Wenn Dich die Ausgabe stört, kannst Du `os.path.normpath()` verwenden den Pfad zu normalisieren.

Re: Kann mal jemand über mein erstes "Programm" gucken?

Verfasst: Mittwoch 9. Mai 2012, 20:36
von knapp
Da tut sich eine Baustelle nach der anderen auf. :)

Wie gesagt, habe ich mein "Programm" selbst nicht für optimal gehalten, aber für meine Zwecke wäre es vermutlich ausreichend, da hier im Höchstfall mal 30 Elemente im Ordner sind. Ich wollte halt auch irgendwie zu einem Ergebnis kommen.

Das Gleiche gilt für die ganzen anderen Detailfragen. Ein Tut. hatte ich mir durchgelesen und auch schon einige andere Seiten zu speziellen Themen bzgl. Python gelesen. Aber alles geht halt nicht gleich beim ersten Mal.

Bzgl. "schnell in einer Python-Shell":
Da musste ich erst mal überlegen, was das überhaupt ist.
Wenn ich in CMD.exe "Python" aufrufe, dann ist das vermutlich die, oder eine Pythonshell.
Dann bin ich darüber gestolpert, dass mir anfangs nicht klar war, dass ich auch in der Shell zuerst os importieren muss, und dass ich das mit getrennten Befehlen machen kann und nicht in eine Befehlszeile eingeben muss.

Wenn man das so schön erklärt bekommt, dann ist das auch alles einleuchtend, aber als ich angefangen hatte, wusste ich nicht, wie ich mal eben schnell eine Hilfe bekomme. Das habe ich mit mir google zusammen gesucht.

Das mit dem try und except lasse ich erst mal beiseite.

os.path.normpath() werde ich ausprobieren.
Ist es richtig, dass man innerhalb von Python bei Pfadangaben beliebig "/" und "\" gegeneinander austauschen kann, wenn man davon absieht, dass das mitunter als Steuerzeichen interpretiert wird?

Re: Kann mal jemand über mein erstes "Programm" gucken?

Verfasst: Mittwoch 9. Mai 2012, 21:27
von BlackJack
@knapp: Ja, eine Python-Shell bekommst Du, wenn Du Python ohne Argumente aufrufst. Oder über das Startmenü wenn Du IDLE startest. Das ist zum „live” ausprobieren und mit Objekten herum zu spielen sehr praktisch.

Was Du als Pfadtrenner benutzen kannst hat nichts mit Python zu tun. Die Frage ist was das Betriebssystem versteht. Und bei Windows geht beides. Unter Linux geht \ nicht.