Benutzung von ZipFile

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
Seeker
User
Beiträge: 70
Registriert: Mittwoch 16. September 2009, 19:52

Hi allerseits!

Ich bin noch völlig neu zu Python (Programmieren allgemein) und habe angefangen, "Byte of Python" durchzuarbeiten. Das theoretische verstehe ich grundsätzlich ziemlich gut, ist alles super erklärt, aber in der Praktik klappts noch nicht ganz ^^.

Es geht um das "Backup-Programm" (Kapitel 10), wo man Files in einen neuen Ordner sichern und diese Files sichern möchte. Da der beschriebene Code für Linux ist, ich jedoch Windows (Vista 32bit) verwende, habe ich mich nach einer Lösung für den fehlenden "zip_command"-Befehl umgeschaut und habe zwei Lösungen gefunden.

Auf Swaroops Seite erklärt er, man solle das Gnu-Programm zur Erstellung von Zipfiles installieren und den Pfad adden. Habe ich gemacht... doch was nun? =/

Darauf habe ich noch herausgefunden, dass es ja einen Pythonbefehl gibt, der zipfiles herstellen sollte. (ZipFile)
Doch auch hier... ich schaffe es einfach nicht, diesen Befehl korrekt einzubetten. Es kommt immer die Nachricht "NameError: name 'ZipFile' is not defined"

Hier die (funktionierende) Version, wie sie auf Linux aussieht:

Code: Alles auswählen

# Filename: backup_ver1.py

import os
import time

source = [r'C:\Users\mewett\Desktop\random', r'C:\Python26\Lib\site-packages\Programmieren']
target_dir = r'D:\backup'
target = target_dir + time.strftime('%Y%m%d%H%M%S') + '.zip'

zip_command = 'zip -qr "%s" "%s"' % (target, ' '.join(source))
if os.system(zip_command) == 0:
    print 'Successful backup to', target
else:
    print 'Backup FAILED'
Vielen Dank im Voraus für Hilfe/Hinweise =)!

Gruss Seeker
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

So sieht die Linux Version jedenfalls nicht aus.

Um helfen zu koennen solltest du das _fehlerhafte_ Programm und den _kompletten_ Traceback angeben.

Hier ist das Problem einfach, dass du ``ZipFile`` nutzt, ohne es importiert zu haben.
1. http://docs.python.org/library/zipfile.html lesen
2. ``import ZipFile``
3. Wiederhole 1.

Edit: Noch ein paar generelle Anmerkungen:
Zum Zusammensetzen vom Pfaden gibt es ``os.path.join``
Um externe Programme aufzurufen ist man mit ``subprocess`` besser dran als mit ``os.system``
Seeker
User
Beiträge: 70
Registriert: Mittwoch 16. September 2009, 19:52

Schonmal Danke für die Antwort!

Also, den obrigen Code habe ich vom Tutorial abgeschrieben, sollte eigentlich schon stimmen (Mit ausnahme der Dateipfade natürlich, die sind auf meinen Rechner/Windows angepasst).

Mein vorheriger Versuch sah etwa so aus:

Code: Alles auswählen

# Filename: backup_ver1.py

import os
import time
import ZipFile

source = [r'C:\Users\mewett\Desktop\random', r'C:\Python26\Lib\site-packages\Programmieren']
target_dir = r'D:\backup'
target = target_dir + time.strftime('%Y%m%d%H%M%S') + '.zip'

z = ZipFile(('zip -qr "%s" "%s"' % (target, ' '.join(source))),"w", ZIP_STORED, allowZip64=False)
Aus Einfachheitsgründen hatte ich erstmals die "Bestätigung" weggelassen. Die Benutzung von ZipFile ist wahrscheinlich falsch, aber naja... wie gesagt, wusste nichts Besseres damit angfangen ;).

Antwort:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Python26\Lib\site-packages\Programmieren\backup_ver1.py", line 12, in <module>
    z = ZipFile(('zip -qr "%s" "%s"' % (target, ' '.join(source))),"w", ZIP_STORED, allowZip64=False)
NameError: name 'ZipFile' is not defined
Ich werde es aber mit dem Zipfile.write Code nochmals versuchen, der im Link angegeben wird. =)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also bei mir heißt das Modul zipfile ;-)

Es sollte also eigentlich ein ImportError kommen...

Und dann schau Dir mal an, wie Du die spezielle Funktion aus time oder os aufrust und dann noch mal Deine Aufruf von ZipFile!

Pfade setzt man am besten nicht mit "+" sondern mit os.join() zusammen. Ich denke Dein "target" sieht nicht so aus, wie es sollte.

Lasse Dir doch mal alle Pfade und zusammengebastelten Dinge vor dem Aufruf von ZipFile ausgeben!
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Hyperion hat geschrieben:Also bei mir heißt das Modul zipfile ;-)
Das war der Test, ob er Punkt 1 und 3 erfuellt .. durchgefallen :(

Und nochmal: goto Punkt 1.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

cofi hat geschrieben:
Hyperion hat geschrieben:Also bei mir heißt das Modul zipfile ;-)
Das war der Test, ob er Punkt 1 und 3 erfuellt .. durchgefallen :(

Und nochmal: goto Punkt 1.
Hab ich doch glatt überlesen :oops:
(Netter Test btw ;-) )
Seeker
User
Beiträge: 70
Registriert: Mittwoch 16. September 2009, 19:52

Ich habe beide Varianten ausprobiert, an der Gross/Kleinschreibung scheint es nicht zu liegen.

Modulbeschreibung:
class ZipFile
Class with methods to open, read, write, close, list zip files.

z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False)

file: Either the path to the file, or a file-like object.
If it is a path, the file will be opened and closed by ZipFile.
mode: The mode can be either read "r", write "w" or append "a".
compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib).
allowZip64: if True ZipFile will create files with ZIP64 extensions when
needed, otherwise it will raise an exception when this would
be necessary.
Hier schien es allerdings klar ZipFile zu heissen.

Aber ZipFile scheint er allerdings nicht zu finden, deshalb nächster Versuch mit zipfile. Ich habe mal versucht, os.path.join() einzusetzen (ich vermute, dass du das gemeint hast).

Code: Alles auswählen

# Filename: backup_ver1.py

import os
import time
import zipfile

source = [r'C:\Users\mewett\Desktop\random', r'C:\Python26\Lib\site-packages\Programmieren']
target_dir = r'D:\backup'
target = os.path.join(target_dir, time.strftime('%Y%m%d%H%M%S'), '.zip')
print source
print target

z = zipfile(('zip -qr "%s" "%s"' % (target, ' '.join(source))),"w", ZIP_STORED, allowZip64=False)
Fehler:

Code: Alles auswählen

['C:\\Users\\mewett\\Desktop\\random', 'C:\\Python26\\Lib\\site-packages\\Programmieren']
D:\backup\20090916220604\.zip

Traceback (most recent call last):
  File "C:\Python26\Lib\site-packages\Programmieren\backup_ver1.py", line 14, in <module>
    z = zipfile(('zip -qr "%s" "%s"' % (target, ' '.join(source))),"w", ZIP_STORED, allowZip64=False)
NameError: name 'ZIP_STORED' is not defined
PS: Die andere Variante mit "write()" habe ich auch versucht... zipfile.write() scheint er nicht zu kennen ("AttributeError: 'module' object has no attribute 'write'")[/quote]
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Jetzt hast du das "@cofi nicht sehr hilfreich" rauseditiert. Wie fies.
Dabei ist es genau das:
http://docs.python.org/library/zipfile.html hat geschrieben:class zipfile.ZipFile
The class for reading and writing ZIP files. See section ZipFile Objects19 for constructor details.
Du musst auch den Modulnamensraum in deine Aufrufe einbeziehen (ungetestet):

Code: Alles auswählen

import os
import time
import zipfile

source = [r'C:\Users\mewett\Desktop\random', r'C:\Python26\Lib\site-packages\Programmieren']
target_dir = r'D:\backup'
target = os.path.join(target_dir, time.strftime('%Y%m%d%H%M%S'), '.zip')
print source
print target

z = zipfile.ZipFile(('zip -qr "%s" "%s"' % (target, ' '.join(source))),"w", zipfile.ZIP_STORED, allowZip64=False)
@Hyperion: Danke :twisted:
Seeker
User
Beiträge: 70
Registriert: Mittwoch 16. September 2009, 19:52

Schnell noch den anderen Link versucht...

Code: Alles auswählen

#!/usr/bin/python
# Filename: backup_ver1.py

import os
import time
import zipfile

source = [r'C:\Users\mewett\Desktop\random', r'C:\Python26\Lib\site-packages\Programmieren']
target_dir = r'D:\backup'
target = os.path.join(target_dir, time.strftime('%Y%m%d%H%M%S'), '.zip')
print source
print target

zipfile.ZipFile(('zip -qr "%s" "%s"' % (target, ' '.join(source))),"w", ZIP_STORED, allowZip64=False)
Fehler der gleiche... =(

*EDIT* Danke, werds gleich testen... vielleicht erkennt er deshalb das ZIP_STORED nicht
Seeker
User
Beiträge: 70
Registriert: Mittwoch 16. September 2009, 19:52

Scheint noch nicht ganz zu klappen, aber die Fehlermeldung ist schon einmal anders ^^.

Code:

Code: Alles auswählen

#!/usr/bin/python
# Filename: backup_ver1.py

import os
import time
import zipfile

source = [r'C:\Users\mewett\Desktop\random', r'C:\Python26\Lib\site-packages\Programmieren']
target_dir = r'D:\backup'
target = os.path.join(target_dir, time.strftime('%Y%m%d%H%M%S'), '.zip')
print source
print target

z = zipfile.ZipFile(('zip -qr "%s" "%s"' % (target, ' '.join(source))),"w", zipfile.ZIP_STORED, allowZip64=False)
Antwort:

Code: Alles auswählen

>>> 
['C:\\Users\\mewett\\Desktop\\random', 'C:\\Python26\\Lib\\site-packages\\Programmieren']
D:\backup\20090916221830\.zip

Traceback (most recent call last):
  File "C:\Python26\Lib\site-packages\Programmieren\backup_ver1.py", line 14, in <module>
    z = zipfile.ZipFile(('zip -qr "%s" "%s"' % (target, ' '.join(source))),"w", zipfile.ZIP_STORED, allowZip64=False)
  File "C:\Python26\lib\zipfile.py", line 680, in __init__
    self.fp = open(file, modeDict[mode])
IOError: [Errno 22] invalid mode ('wb') or filename: 'zip -qr "D:\\backup\\20090916221830\\.zip" "C:\\Users\\mewett\\Desktop\\random C:\\Python26\\Lib\\site-packages\\Programmieren"'
Sry, ich schaff es noch nicht, aus diesen Fehlermeldungen schlau zu werden. Er mag das z = zipfile... nicht, das ist klar. Aber was hat das mit dem self.fp zu tun? =/
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich haette mich nich darauf verlassen sollen, dass du wenigstens den zitierten Teil gelesen hast.

Meine Zeile 11 muss so heissen:

Code: Alles auswählen

z = zipfile.ZipFile(target, "w", zipfile.ZIP_STORED, allowZip64=False)
Btw du musst die Dateien danach in dein ``ZipFile`` Objekt schreiben, das funktioniert nicht so komfortabel wie mit dem `zip` Programm .. siehe Doku.

Edit: das hat nichts mit ``self.fp`` zu tun, stammt ja auch aus ``zipfile.ZipFile``, sondern damit, dass

Code: Alles auswählen

'zip -qr "D:\\backup\\20090916221830\\.zip" "C:\\Users\\mewett\\Desktop\\random C:\\Python26\\Lib\\site-packages\\Programmieren"'
schlicht kein gueltiger Dateiname ist.
Seeker
User
Beiträge: 70
Registriert: Mittwoch 16. September 2009, 19:52

*EDIT* Hatte Edits noch nicht gelesen. Werde es unter diesem Gesichtspunkt nochmals anschauen.



Habs schon gelesen... allerdings wohl falsch verstanden..
Was mich verwirrt, ist, dass "Open a Zip File" steht... wobei es ja mein Ziel ist, ein nicht-existierendes File zu kreieren.

Ungefähr so?:

Code: Alles auswählen

# Filename: backup_ver1.py

import os
import time
import zipfile

source = [r'C:\Users\mewett\Desktop\random', r'C:\Python26\Lib\site-packages\Programmieren']
target_dir = r'D:\backup'
target = os.path.join(target_dir, time.strftime('%Y%m%d%H%M%S'), '.zip')
print source
print target

z = zipfile.ZipFile(target, "w", zipfile.ZIP_STORED, allowZip64=False)
Antwort:

Code: Alles auswählen

>>> 
['C:\\Users\\mewett\\Desktop\\random', 'C:\\Python26\\Lib\\site-packages\\Programmieren']
D:\backup\20090916223208\.zip

Traceback (most recent call last):
  File "C:\Python26\Lib\site-packages\Programmieren\backup_ver1.py", line 14, in <module>
    z = zipfile.ZipFile(target, "w", zipfile.ZIP_STORED, allowZip64=False)
  File "C:\Python26\lib\zipfile.py", line 680, in __init__
    self.fp = open(file, modeDict[mode])
IOError: [Errno 2] No such file or directory: 'D:\\backup\\20090916223208\\.zip'
Naja... ich will dich nicht die ganze Nacht mit dem langweilen ^^. Ich versuchs sonst noch morgen und meld mich am Abend wieder falls ich immer noch keine Lösung gefunden habe =). Danke für die Geduld ;)

*EDIT**EDIT* "No such file or directory:"... natürlich gibt das nicht, das soll ja erstellt werden... aber ich habe keinen anderen Befehl zur "neuerstellung" von zipfiles gefunden...
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Seeker hat geschrieben:*EDIT**EDIT* "No such file or directory:"... natürlich gibt das nicht, das soll ja erstellt werden... aber ich habe keinen anderen Befehl zur "neuerstellung" von zipfiles gefunden...
Nein, du musst die Fehlermeldung auch richtig lesen, denn das Problem ist, dass es kein _directory_ mit dem Namen gibt und deshalb auch keines in des eine Datei namens `.zip` geschrieben werden kann.

Und generell gilt, oeffnest du eine Datei mit ``w``, dann schreibst du eine neue Datei mit dem Namen und ueberschreibst die Datei mit demselben Namen, wenn es eine gab.

Aender Zeile 9 zu

Code: Alles auswählen

target = os.path.join(target_dir, "%s.zip" % time.strftime('%Y%m%d%H%M%S'))
Seeker
User
Beiträge: 70
Registriert: Mittwoch 16. September 2009, 19:52

Es funktioniert!! :D
Warum es drauf ankommt ob "x"+".zip" oder "%s.zip" % x, leuchtet mir nicht ganz ein, aber das war das Problem =)

Vielen Dank für die Hilfe! =)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Seeker hat geschrieben:Warum es drauf ankommt ob "x"+".zip" oder "%s.zip" % x, leuchtet mir nicht ganz ein, aber das war das Problem =)
Nein darauf kommt es nicht an, das Problem war, dass du ``os.path.join`` falsch benutzt hast und zwar so, dass das Datum als Ordner und das ".zip" als Datei behandelt wurde.
Du haettest auch

Code: Alles auswählen

target = os.path.join(target_dir, time.strftime('%Y%m%d%H%M%S') + ".zip")
benutzen koennen, aber String Formatting ist zu bevorzugen.
Seeker
User
Beiträge: 70
Registriert: Mittwoch 16. September 2009, 19:52

Achso, ich dachte, dass es einfach auf die Reihenfolge drauf an kommt, d.h. die Strings wirklich nur aneinandergehängt werden... aber jetzt ises klar, danke =).
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Auf das Problem mit dem Ordner hatte ich bereits ganz am Anfang hingewiesen ;-)
Seeker
User
Beiträge: 70
Registriert: Mittwoch 16. September 2009, 19:52

Also... ich habe heute weiter am Programm rumgetüftelt. Gestern Abend war es ja in der Lage, einen neuen Zipordner zu erstellen.
Nach einem langen Tag habe ich es nun endlich geschafft (kein Kommentar...), dass er alle Dateien aus einem Ordner nimmt, richtig umbenennt und im Zipordner speichert.

Code: Alles auswählen

# Filename: backup_ver1b.py

import os
import time
import zipfile

source = [r'C:\Users\mewett\Desktop\random']
target_dir = r'D:\backup'
target = os.path.join(target_dir, "%s.zip" % time.strftime('%Y%m%d%H%M%S'))
print "Source:", source
print "Target:", target

path=r'C:\Users\mewett\Desktop\random'
dirList=os.listdir(path)
z = zipfile.ZipFile(target, "w", zipfile.ZIP_STORED, allowZip64=False)
for i in dirList:
    fpath = r"C:\Users\mewett\Desktop\random"+"\\"+i
    print fpath
    z.write(fpath,i)
    print "Backup for %s successful" %i
Mein Hauptproblem war es, hinzukriegen, dass in z.write() einerseits zuerst der ganze Pfad eingeschleust wird, danach aber nur Dateiname.Endung. Nach vielen Versuchen mit dirList und os.path.walk habe ich keine andere Lösung als " "+ " " Patchwork gefunden...
Kann man dies auch mit os.path.join erreichen (Zeile 17)? Bei mir hat er dann nämlich jeweils nur den Dateinamen (nicht den ganzen Pfad) ausgespuckt =/.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dann hast Du wohl etwas falsch gemacht:

Code: Alles auswählen

In [1]: import os.path

In [2]: import os

In [3]: dir = os.listdir(".")

In [4]: dir
Out[4]:
['easy_install-2.6-script.py',
 'easy_install-2.6.exe',
 'easy_install-script.py',
 'easy_install.exe',
 'ipcluster-script.py',
 'ipcluster.exe',
 'ipcontroller-script.py',
 'ipcontroller.exe',
 'ipengine-script.py',
 'ipengine.exe',
 'iptest-script.py',
 'iptest.exe',
 'ipython-script.py',
 'ipython.exe',
 'ipythonx-script.py',
 'ipythonx.exe',
 'pycolor-script.py',
 'pycolor.exe']

In [5]: for element in dir:
   ...:     print os.path.join(r"C:\\Users\mewett\Desktop\random", element)
   ...:
   ...:
C:\\Users\mewett\Desktop\random\easy_install-2.6-script.py
C:\\Users\mewett\Desktop\random\easy_install-2.6.exe
C:\\Users\mewett\Desktop\random\easy_install-script.py
C:\\Users\mewett\Desktop\random\easy_install.exe
C:\\Users\mewett\Desktop\random\ipcluster-script.py
C:\\Users\mewett\Desktop\random\ipcluster.exe
C:\\Users\mewett\Desktop\random\ipcontroller-script.py
C:\\Users\mewett\Desktop\random\ipcontroller.exe
C:\\Users\mewett\Desktop\random\ipengine-script.py
C:\\Users\mewett\Desktop\random\ipengine.exe
C:\\Users\mewett\Desktop\random\iptest-script.py
C:\\Users\mewett\Desktop\random\iptest.exe
C:\\Users\mewett\Desktop\random\ipython-script.py
C:\\Users\mewett\Desktop\random\ipython.exe
C:\\Users\mewett\Desktop\random\ipythonx-script.py
C:\\Users\mewett\Desktop\random\ipythonx.exe
C:\\Users\mewett\Desktop\random\pycolor-script.py
C:\\Users\mewett\Desktop\random\pycolor.exe
Seeker
User
Beiträge: 70
Registriert: Mittwoch 16. September 2009, 19:52

Super, danke für die schnelle Antwort =). Der Fehler war, dass ich "C:\....\random\", i eingegeben hatte, um einen \ drinzuhaben (was nicht akzeptiert wurde). Daraufhin habe ich es mit "C:\...\random",r"\",i) versucht, ging auch nicht.
Ich hatte übersehen, dass er die \ ja automatisch einfügt, und ihn ein zusätzlicher \ deshalb wohl verwirrt.

*Edit*:
letztes Update:
Ich habe den Code ein wenig verbessert. Man kann nun mehrere Ordnerpfade eingeben. Diese Version hier komprimiert auch noch das ganze. Es braucht länger, aber das End-Zipfile ist doch bedeutend kleiner.
Dazu, ähnlich wie im Script beschrieben, entsteht jeweils ein Ordner mit dem Datum (falls er noch nicht exisitiert) und der Zipordner zeigt dann die Zeit des Backups an.

Code: Alles auswählen

import os
import time
import zipfile
import zlib

source = [r'C:\Users\mewett\Desktop\random', r'C:\Users\mewett\Desktop\Schule Buchhaltung']
target_dir = r'D:\backup'
print "Source:", source

today = os.path.join(target_dir,time.strftime('%Y-%m-%d'))

target = os.path.join(today, "%s.zip" % time.strftime('%Hh%M'))
print "Target:", target

if not os.path.exists(today):
    os.mkdir(today)
    print 'Successfully created new directory'

z = zipfile.ZipFile(target, "w", zipfile.ZIP_DEFLATED, allowZip64=False)

for item in source:
    path=item
    dirList=os.listdir(path)
    for i in dirList:
        fpath = os.path.join(path, i)
        print fpath
        z.write(fpath,i)
        print "Backup for %s successful" %i
Antworten