Есть ли способ прервать операцию shutil copytree в Python?

Я новичок в программировании в целом. Мне нужно разработать программу, которая может копировать несколько каталогов одновременно, а также учитывать исключения для нескольких типов файлов. Я наткнулся на модуль shutil, который предлагает функции copytree и ignore_patterns. Вот фрагмент моего кода, который также использует диалог нескольких каталогов wxPython:

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()

Этот код мне подходит. Иногда я копирую данные объемом в терабайты. Есть ли вообще возможность прерывания shutil.copytree? Я спрашиваю об этом, потому что в первый раз, когда я запустил эту программу, я выбрал довольно большой каталог и случайно скопировал тонну файлов (Успешно!) И хотел остановить это :(. Как только я обойду это, я, наконец, начну на графическом интерфейсе! Если есть дополнительная информация, которую я могу предоставить, пожалуйста, дайте мне знать! Заранее благодарим за любую помощь!


person Travis Mitchell    schedule 17.12.2018    source источник


Ответы (2)


Вы можете запустить копию в отдельном процессе Python, используя модуль multiprocessing. Код может выглядеть примерно так:

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()

В моем примере основной процесс запускает дочерний процесс, который выполняет фактическое копирование, и через 3 секунды завершает его. Также вы можете проверить, запущен ли процесс, вызвав is_alive() метод процесса.

person Vladimir Poghosyan    schedule 17.12.2018
comment
если вы прервете процесс, вы, скорее всего, оставите частично переданные файлы - person user2682863; 17.12.2018
comment
После завершения вы можете проверить, есть ли скопированные файлы, и очистить их (целевой каталог). - person Vladimir Poghosyan; 17.12.2018

copytree принимает в качестве параметра copy_function. Если вы передадите функцию, которая проверяет наличие флага, вы можете вызвать ошибку, чтобы прервать операцию.

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)
person user2682863    schedule 25.12.2018
comment
Я считаю, что это остановит копирование дерева между файлами, но не во время отдельного копирования. Это может быть или не быть достаточно хорошим решением исходного вопроса, в зависимости от размера файлов. - person gkimsey; 15.09.2020