Folgendes Programm soll einen Ordner per shutil.copytree() in zwei verschiedene Zielordener kopieren.
Wenn im Zielordner bereits ein Ordner mit gleichem Namen vorhanden, dann soll dieser vorher als .zip archiviert und
in den Ordner "archive" verschoben werden.
Problem ist, dass ab und zu ein PermissionError bei shutil.copytree() auftritt.
- System Windows 7 64bit
- Python 3.5
- bin als Admin angemeldet
- Kommandozeile wird als Admin ausgeführt
Wie kann den ein Zugriff auf einen Ordner verweigert werden, der eigentlich zuvor gelöscht wurde und mit copytree() erst wieder erzeugt wird?
Hab ich was übersehen?
Code: Alles auswählen
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import os
import shutil
from datetime import datetime
class MainApp(tk.Tk):
def __init__(self):
super().__init__()
self.title('Backup tool')
self.main_frame = MainFrame(self).pack(side='top', fill='both', expand=True)
def start(self):
self.mainloop()
class MainFrame(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.source = tk.StringVar()
self.dst = tk.StringVar()
self.dst_2 = tk.StringVar()
# self.source.set('C:\\Users\\ssb\\Desktop\\copytree\\prepro5')
# self.dst.set('C:\\Users\\ssb\\Desktop\\copytree2')
# self.dst_2.set('C:\\Users\\ssb\\Desktop\\copytree3')
self.source_entry = ttk.Entry(self, width=50, textvariable=self.source)
self.dst_entry = ttk.Entry(self, width=50, textvariable=self.dst)
self.dst_2_entry = ttk.Entry(self, width=50, textvariable=self.dst_2)
self.source_button = ttk.Button(self,
text='Source',
command=lambda: self._choose_dir(self.source))
self.dst_button = ttk.Button(self,
text='Destination 1',
command=lambda: self._choose_dir(self.dst))
self.dst_2_button = ttk.Button(self,
text='Destination 2',
command=lambda: self._choose_dir(self.dst_2))
self.backup_button = ttk.Button(self, text='Backup', command=self._backup)
self.source_entry.grid(row=0, column=0, sticky='nswe')
self.dst_entry.grid(row=1, column=0, sticky='nswe')
self.dst_2_entry.grid(row=2, column=0, sticky='nswe')
self.source_button.grid(row=0, column=1, sticky='nswe')
self.dst_button.grid(row=1, column=1, sticky='nswe')
self.dst_2_button.grid(row=2, column=1, sticky='nswe')
self.backup_button.grid(row=3, column=0, columnspan=2, sticky='nswe')
def _choose_dir(self, tkvar_to_set):
dir_path = filedialog.askdirectory()
tkvar_to_set.set(dir_path)
def _backup(self):
if os.path.isdir(self.source.get()):
backup_status = []
for index, folder in enumerate([self.dst.get(), self.dst_2.get()]):
# check if destination path is valid directory
if os.path.isdir(folder):
dst_folder = os.path.join(folder, os.path.basename(self.source.get()))
# check if destination folder exists and archive it
if os.path.isdir(dst_folder):
self._archive_old(dst_folder)
shutil.copytree(self.source.get(), dst_folder)
backup_status.append('Source backup saved to destination {0}: {1}'.format(index + 1, dst_folder))
else:
backup_status.append('Destination {0} not defined'.format(index + 1))
messagebox.showinfo('Info...', '{0}\n{1}'.format(backup_status[0], backup_status[1]))
else:
messagebox.showerror('Error...', 'Please define a valid source directory and try again')
def _archive_old(self, dst_folder):
file_name = '{}_{}'.format(os.path.basename(dst_folder),
datetime.today().strftime('%Y%m%d'))
archive_path = os.path.join(os.path.dirname(dst_folder), 'archive', file_name)
shutil.make_archive(archive_path, 'zip',
os.path.dirname(dst_folder),
os.path.basename(dst_folder))
shutil.rmtree(dst_folder)
if __name__ == '__main__':
MainApp().start()
Code: Alles auswählen
Traceback (most recent call last):
File "C:\Users\ssb\AppData\Local\Continuum\Miniconda3\envs\msp_py35\lib\tkinter\__init__.py", line 1558, in __call__
return self.func(*args)
File "backup.py", line 70, in _backup
shutil.copytree(self.source.get(), dst_folder)
File "C:\Users\ssb\AppData\Local\Continuum\Miniconda3\envs\msp_py35\lib\shutil.py", line 315, in copytree
os.makedirs(dst)
File "C:\Users\ssb\AppData\Local\Continuum\Miniconda3\envs\msp_py35\lib\os.py", line 241, in makedirs
mkdir(name, mode)
PermissionError: [WinError 5] Zugriff verweigert: 'C:\\Users\\ssb\\Desktop\\copytree2\\prepro5'