Suche Hilfe bei ersten Gehversuchen

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
frank2342
User
Beiträge: 7
Registriert: Dienstag 26. August 2008, 17:00

Hallo zusammen,

ich starte gerade meine ersten Gehversuche mit Python. Dabei soll am Ende ein kleines Backupscript rauskommen.

Das Ganze sieht im Moment folgendermaßen aus:

Code: Alles auswählen

#!/usr/bin/python

#############
# Functions #
#############

import os
import os.path
import shutil
import time
import subprocess

def GET_TIME():
	return time.strftime("%d.%m.%Y %H:%M:%S", time.localtime())

def DO_RDIFF(SOURCE, TARGET, EXCLUDE, LOGFILE):
	
	LOG = file(LOGFILE, 'a')
	LOG.write(GET_TIME() + " " + SOURCE + "\n")
	
	if os.path.isdir(TARGET) == False:
		os.system("mkdir -p " + TARGET)
		LOG.write(GET_TIME() + " " + TARGET + " created \n")
	
	CMD = "rdiff-backup --print-statistics " + EXCLUDE + " " + SOURCE + " " + TARGET
	subprocess.call(CMD, stdout=LOG, stderr=LOG)
	LOG.write(GET_TIME() + " done \n\n")
	LOG.close()

#############
# WebFolder #
#############

SOURCE = "/var/www/"
TARGET = "/var/backups/vserver/www/"
LOGFILE = "/var/backups/vserver/backup.log"

EXCLUDE = ""
EXCLUDE = EXCLUDE + " --exclude **backups"
EXCLUDE = EXCLUDE + " --exclude ***.log"
EXCLUDE = EXCLUDE + " --exclude **phptmp"
EXCLUDE = EXCLUDE + " --exclude ***.tmp"

DO_RDIFF(SOURCE, TARGET, EXCLUDE, LOGFILE)
Starte ich das Script erhalte ich folgende Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "./rbackup2.py", line 44, in ?
    DO_RDIFF(SOURCE, TARGET, EXCLUDE, LOGFILE)
  File "./rbackup2.py", line 26, in DO_RDIFF
    subprocess.call(CMD, stdout=LOG, stderr=LOG)
  File "/usr/lib/python2.4/subprocess.py", line 413, in call
    return Popen(*args, **kwargs).wait()
  File "/usr/lib/python2.4/subprocess.py", line 543, in __init__
    errread, errwrite)
  File "/usr/lib/python2.4/subprocess.py", line 975, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
Der Befehl in "CMD" wird auf jeden Fall richtig zusammengesetzt. Lasse ich mir den Befehl mit print ausgeben und führe den direkt in der Shell aus funktioniert alles wie gewollt. Irgendwie hakt es an "subprocess.call". Mit meinem Latein bin ich vorerst am Ende. Dazu fehlt mir die Erfahrung in Python. Ihr könnt mir aber sicher ganz schnell auf die Sprünge helfen wo mein Fehler liegt.

Viele Grüße
Frank
lunar

subprocess.call nimmt eine Liste als erstes Argument entgegen. Im Übrigen kannst du den os.system Aufruf bei der Gelegenheit auch gerade ersetzen.

Desweiteren ist es im Bezug auf die Namensgebung in Python üblich, die Regeln des Styleguides PEP 8 einzuhalten. Danach sind Großbuchstaben für Konstanten reserviert, Funktionen und "normale" Namen werden klein geschrieben.

Außerdem solltest du den Aufruf von "file" mit entsprechender Ausnahmebehandlung versehen und "file" vielleicht auch gleich durch "open" ersetzen.
frank2342
User
Beiträge: 7
Registriert: Dienstag 26. August 2008, 17:00

lunar hat geschrieben:subprocess.call nimmt eine Liste als erstes Argument entgegen. Im Übrigen kannst du den os.system Aufruf bei der Gelegenheit auch gerade ersetzen.
ich habe aus

Code: Alles auswählen

os.system("mkdir -p " + TARGET)

Code: Alles auswählen

subprocess.call("mkdir", "-p " + target)
gemacht. Jetzt bricht das Script allerdings schon an der Stelle ab:

Code: Alles auswählen

Traceback (most recent call last):
  File "./rbackup2.py", line 44, in ?
    do_rdiff(source, target, exclude, logfile)
  File "./rbackup2.py", line 22, in do_rdiff
    subprocess.call("mkdir", "-p " + target)
  File "/usr/lib/python2.4/subprocess.py", line 413, in call
    return Popen(*args, **kwargs).wait()
  File "/usr/lib/python2.4/subprocess.py", line 494, in __init__
    raise TypeError("bufsize must be an integer")
TypeError: bufsize must be an integer
lunar hat geschrieben:Desweiteren ist es im Bezug auf die Namensgebung in Python üblich, die Regeln des Styleguides PEP 8 einzuhalten. Danach sind Großbuchstaben für Konstanten reserviert, Funktionen und "normale" Namen werden klein geschrieben.
OK, so kenne ich es von PHP auch. Hatte nur hier zum lernen Großbuchstaben verwendet.
lunar hat geschrieben:Außerdem solltest du den Aufruf von "file" mit entsprechender Ausnahmebehandlung versehen und "file" vielleicht auch gleich durch "open" ersetzen.
Sobald ich die basics drauf habe baue ich das Script aus.
lunar

Was genau hast du an "subprocess.call nimmt eine Liste als erstes Argument entgegen" nicht verstanden?
frank2342
User
Beiträge: 7
Registriert: Dienstag 26. August 2008, 17:00

lunar hat geschrieben:Was genau hast du an "subprocess.call nimmt eine Liste als erstes Argument entgegen" nicht verstanden?
Sorry, aber wenn du so fragst wahrscheinlich alles.

Code: Alles auswählen

cmd = ["mkdir", "-p", target]
subprocess.call(cmd)
damit funktioniert jetzt erstmal das anlegen des Verzeichnis wieder.

Also wenn ich das jetzt richtig verstanden habe, MUSS das erste Argument eine Liste sein. Auch wenn die Liste mal nur einen einzigen Wert hat.

Das gleiche habe ich versucht auf den nächsten Aufruf anzuwenden

Code: Alles auswählen

cmd = ["rdiff-backup", "--print-statistics", exclude, source, target]
subprocess.call(cmd, stdout=log, stderr=log)
Ohne Erfolg. Im Log-File steht:

Code: Alles auswählen

Fatal Error: Switches missing or wrong number of arguments
See the rdiff-backup manual page for more information.
lunar

frank2342 hat geschrieben:damit funktioniert jetzt erstmal das anlegen des Verzeichnis wieder.
Btw, "os.mkdir" und "os.makedirs" existieren.
Also wenn ich das jetzt richtig verstanden habe, MUSS das erste Argument eine Liste sein. Auch wenn die Liste mal nur einen einzigen Wert hat.
Ja.
Das gleiche habe ich versucht auf den nächsten Aufruf anzuwenden

Code: Alles auswählen

cmd = ["rdiff-backup", "--print-statistics", exclude, source, target]
subprocess.call(cmd, stdout=log, stderr=log)
Ohne Erfolg. Im Log-File steht:

Code: Alles auswählen

Fatal Error: Switches missing or wrong number of arguments
See the rdiff-backup manual page for more information.
Wenn dich das wundert, dann lass dir deine "cmd"-Liste mal mit "print" ausgeben. Das ist nämlich keine richtige Argumentliste.
frank2342
User
Beiträge: 7
Registriert: Dienstag 26. August 2008, 17:00

lunar hat geschrieben: Wenn dich das wundert, dann lass dir deine "cmd"-Liste mal mit "print" ausgeben. Das ist nämlich keine richtige Argumentliste.

Code: Alles auswählen

['mkdir', '-p', '/var/backups/vserver/www/']
['rdiff-backup', '--print-statistics', ' --exclude **backups', '/var/www/', '/var/backups/vserver/www/']
der einzige Unterschied den ich feststellen kann ist die Länge der Liste. Verkürze ich die Liste auch auf drei Werte:

Code: Alles auswählen

cmd = ["rdiff-backup", "--print-statistics" + exclude, source + " " + target]

Code: Alles auswählen

['rdiff-backup', '--print-statistics --exclude **backups', '/var/www/ /var/backups/vserver/www/']
bekomme ich wieder die Fehlermeldung:

Code: Alles auswählen

Fatal Error: Bad commandline options: option --print-statistics --exclude **backups not recognized
See the rdiff-backup manual page for more information.
frank2342
User
Beiträge: 7
Registriert: Dienstag 26. August 2008, 17:00

ich verstehe es einfach nicht. So funktioniert es:

Code: Alles auswählen

cmd = ["rdiff-backup", source, target]
Aber wie bekomme ich die zusätzlich Optionen --print-statistics und die excludes da noch mit rein?
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Probier's mal so:

Code: Alles auswählen

['rdiff-backup', '--print-statistics', '--exclude',  '**backups', '/var/www/', '/var/backups/vserver/www/'] 
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
BlackJack

Schau Dir die Fehlermeldung noch einmal *genau* an: `rdiff-backup` meckert, dass es die Option (einzahl!) '--print-statistics --exclude **backups' nicht kennt. Was Du da machst entspricht in der Shell einem:

Code: Alles auswählen

rdiff-backup '--print-statistics --exclude **backups' '/var/www/ /var/backups/vserver/www/'
Du musst die einzelnen Argumente auch wirklich *einzeln* in der Liste aufführen.

Code: Alles auswählen

['rdiff-backup', '--print-statistics', '--exclude', '**backups', '/var/www/', '/var/backups/vserver/www/']
Edit: Mist zu langsam. :-)
frank2342
User
Beiträge: 7
Registriert: Dienstag 26. August 2008, 17:00

Aaahhhh, jetzt (nachdem ich noch das Leerzeichen vor --exclude entfernt habe) funktioniert es.

Code: Alles auswählen

cmd = ['rdiff-backup', '--print-statistics', '--exclude',  '**backups', '/var/www/', '/var/backups/vserver/www/']
Als kurze Zusammenfassung:
subprocess.call verlangt als erstes IMMER eine Liste. In dieser Liste muss JEDE EINZELNE OPTION als Wert enthalten sein. Man kann also keine Optionen zusammenfassen und darf keine Leerzeichen verwenden. Richtig so?
frank2342
User
Beiträge: 7
Registriert: Dienstag 26. August 2008, 17:00

Super, Vielen Dank an alle.
Antworten