6

I'm fairly new to programming in general. I need to develop a program that can copy multiple directories at once and also take into account multiple file type exceptions. I came across the shutil module which offers the copytree and ignore_patterns functions. Here is a snippet of my code which also uses the wxPython Multiple Directory Dialog:

import os
import wx
import wx.lib.agw.multidirdialog as MDD
from shutil import copytree
from shutil import ignore_patterns

app = wx.App(0)
dlg = MDD.MultiDirDialog(None, title="Custom MultiDirDialog", defaultPath=os.getcwd(),  agwStyle=MDD.DD_MULTIPLE|MDD.DD_DIR_MUST_EXIST)

dest = "Destination Path"

if dlg.ShowModal() != wx.ID_OK:
    dlg.Destroy()

paths = dlg.GetPaths()

ext = ['*.tiff', '*.raw', '*.p4p', '*.hkl', '*.xlsx']

for path in enumerate(paths):
    directory = path[1].replace('Local Disk (C:)','C:')
    copytree(directory, dest, ignore=ignore_patterns(directory, *ext))

dlg.Destroy()
app.MainLoop()

This code works well for me. At times, I'll be copying terabytes worth of data. Is there anyway that the shutil.copytree can be interrupted? I ask this, because the first time I ran this program, I selected a rather large directory and copied a ton of files (Successfully!) by accident and wanted to stop it :( . Once I get around this, I'll finally start on the GUI! If there is anymore information that I can provide, please let me know! Thanks in advance for any and all help!

2 Answers2

2

You can run the copy in separate python process using multiprocessing module. The code may look something like this:

import time
import shutil
from multiprocessing import Process


def cp(src: str, dest: str):
    shutil.copytree(src, dest)


if __name__ == '__main__':
    proc = Process(target=cp, args=('Downloads', 'Tmp'), daemon=True)
    proc.start()
    time.sleep(3)
    proc.terminate()

In my example the main process starts a child process, which does the actual coping, and after 3 seconds terminates it. Also you can check if the process is running by calling is_alive() method of the process.

1

copytree accepts copy_function as a parameter. If you pass a function that checks for a flag you could raise an error to interrupt the operation.

from shutil import copytree, copy2

# set this flag to True to interrupt a copytree operation
interrupt = False


class Interrupt(Exception):
    """ interrupts the copy operation """


def interruptable_copy(*args, **kwargs):
    if interrupt:
        raise Interrupt("Interrupting copy operation")
    return copy2(*args, **kwargs)


copytree(src, dst, copy_function=interruptable_copy)
user2682863
  • 3,097
  • 1
  • 24
  • 38
  • I believe this will stop the tree copy *between* files, but not during an individual copy. This may or may not be a good enough solution for the original question, depending on how big the files are. – gkimsey Sep 15 '20 at 19:41