Verständniss Frage if Schleife

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
taake
User
Beiträge: 125
Registriert: Donnerstag 14. Oktober 2010, 08:49

Moin, ich wollte ein script was ich im Netz gefunden habe etwas umschreiben, zur Zeit splitet es Dateien (nach Anzahl) in subdirs.
Ich wollte es jetzt etwas umbiegen das es mir die Daten anhand der Dateigröße in subdirs splittet, da ich gelegentlich größere Datenmengen für die offlinefraktion auf CD Brennen darf.

Allerdings benutzt der Author eine If kondition die ich nicht verstehe, daher hoffe ich das mir das hier jemand erklären kann was das genau bedeutet.

Code: Alles auswählen

i = 0
curr_subdir = None
N = 20
for f in files:
    # create new subdir if necessary
        if i % N == 0:
            subdir_name = os.path.join(abs_dirname, '{0:03d}'.format(i / N + 1))
            os.mkdir(subdir_name)
            curr_subdir = subdir_name

        # move file to current dir
        f_base = os.path.basename(f)
        try:
            shutil.move(f, os.path.join(subdir_name, f_base))
        except:
            pass
        i += 1

hier nur die relevante Funktion, verstehe nicht was das genau das % in der If-Schleife bedeutet,
N gibt im übrigen an wie viele Dateien in einen Ordner sollen (soll abgeändert werden das er vorher die Größe der Dateien berechnet und daran fest macht, was auch nicht das Problem ist)
Verstehe nur nicht was das % hier bedeutet und auch die (i / N + 1) Rechnung in
subdir_name = os.path.join(abs_dirname, '{0:03d}'.format(i / N + 1))
Erschließt sich mir nicht ganz was aber ggf. daran liegt das ich die Bedeutung des % nicht kenne.

Hoffe hier kann Jemand kurz Licht ins Dunkel bringen.

Danke im Vorraus
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

taake hat geschrieben: ...verstehe nicht was das genau das % in der If-Schleife bedeutet,
Dazu gleich erstmal der obligatorische Link: if-schleife ;-)
taake hat geschrieben: Verstehe nur nicht was das % hier bedeutet ...
Das ist der Modulo-Operator. Er berechnet also den (ganzzahligen) Rest einer Division.

Das kannst Du einfach in einer Python-Shell ausprobieren:

Code: Alles auswählen

 3 % 1
> 0

 3 % 2
> 1

 3 % 3
> 0

 3 % 4
> 3

 3 % 5
> 3
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
taake
User
Beiträge: 125
Registriert: Donnerstag 14. Oktober 2010, 08:49

Danke für den Link :mrgreen:

Und danke für die Erklärung ;)
BlackJack

@taake: Noch ein paar Anmerkungen zu dem Quelltext:

`curr_subdir` wird nirgends verwendet und wäre auch redundant weil der Name (nahezu) immer an den selben Wert gebunden ist wie `subdir_name`.

Statt `i` manuell vor der Schleife zu initialisieren und in/am Ende der Schleife hochzuzählen würde sich die `enumerate()`-Funktion anbieten.

Die Namen könnten besser sein. `N` und `f` sind sehr nichtssagend. Bei `file_count_per_folder` und `source_path` weiss der Leser wesentlich schneller was die Werte dahinter bedeuten.

Beim dividieren würde ich den ``//``-Operator benutzen um deutlich zu machen, dass hier nur der ganzzahlige Anteil der Division interessiert, und damit der Code nicht kaputt geht wenn man ``from __future__ import division`` verwendet, und damit der Code leichter nach Python 3 portierbar ist.

Die Ausnahme sollte man nicht so einfach komplett verschlucken. Man sollte wenigstens die möglichkeit Vorsehen sich die Ausnahme plus Traceback auf Wunsch anzeigen zu lassen. Das `logging`-Modul bietet sich an der Stelle an.

Code: Alles auswählen

def move_files(target_base_path, source_paths, count_per_folder=20):
    for i, source_path in enumerate(source_paths):
        if i % count_per_folder == 0:
            target_path = os.path.join(
                target_base_path, '{0:03d}'.format(i // count_per_folder + 1)
            )
            os.mkdir(target_path)
        try:
            shutil.move(
                source_path,
                os.path.join(target_path, os.path.basename(source_path))
            )
        except:
            pass  # TODO At least log the exception somewhere.
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ein nacktes `except` ist fast immer schlecht. Wenn man bestimmte Fehlerfälle ignorieren möchte, dann sollte man diese im Code benennen. Beim vorliegenden Beispiel bietet sich innerhalb der Schleife etwas in dieser Art an:

Code: Alles auswählen

try:
    # etwas Code
except (IOError, OSError) as error:
    if not error_handler:
        raise
    error_handler(i, source_path, error)
Antworten