Заставить python ждать, пока subprocess.call завершит свою команду - PullRequest
0 голосов
/ 14 февраля 2020

Таким образом, этот вопрос следует из этого (Прочтите комментарии, а также тот путь, который я выбрал). Я просто хочу, чтобы первый вызов robocopy завершил выполнение sh, прежде чем перейти к остальной части кода. Поскольку я хочу, чтобы вторая robocopy просто пропустила все файлы, так как они уже были скопированы. Однако происходит то, что остальная часть сценария будет работать (ie запускает вторую robocopy), пока первая robocopy копирует файлы. Ниже приведен код:

call(["start", "cmd", "/K", "RoboCopy.exe", f"{self.srcEntry.get()}", f"{self.dstEntry.get()}", "*.*", "/E", "/Z", "/MT:8"], stdout=PIPE, shell=True) 
temp2 = Popen(["RoboCopy.exe", f"{self.srcEntry.get()}", f"{self.dstEntry.get()}", "*.*", "/E", "/Z"], stdout=PIPE, stdin=PIPE, shell=True)

РЕДАКТИРОВАТЬ 1:

Проблема заметна при копировании больших файлов. Я думаю о включении функции сна, которая зависит от общего размера копируемых файлов. Однако это не учитывает скорости загрузки / выгрузки, поскольку файлы будут передаваться по сети.

Ответы [ 3 ]

0 голосов
/ 14 февраля 2020

Что я узнал: благодаря QuantumChris. Я обнаружил, что robocopy возвращается из терминала и возвращается в мой сценарий, хотя я использовал subprocess.run, который должен был приостанавливать мой сценарий до его завершения. Я остановил запуск второй robocopy, проверив, скопированы ли файлы в папку назначения, прежде чем приступить ко второй robocopy. Проблема в том, что если последний файл большой, то os.path.isfile () обнаружит файл WHILE , который все еще копируется. Таким образом, он задействует вторую robocopy, однако вторая robocopy не обнаруживает этот последний файл и пытается скопировать файл, но признает, что не может получить доступ к файлу, поскольку он уже используется (первой robocopy), поэтому он ожидает 30 секунд, прежде чем пытаться снова. Через 30 секунд он может получить доступ к файлу и скопировать его. Теперь я хотел бы сделать мой последний файл пустым фиктивным файлом, который меня не волнует, если он будет скопирован дважды, поскольку он пуст. Robocopy, кажется, копирует файлы в соответствии с порядком ASCII. Итак, я назвал файл ~~~~~ .txt: D

0 голосов
/ 14 февраля 2020

Попробуйте:

while temp2.poll() is not None:
    # ... do something else, sleep, etc

out, err = temp2.communicate()
0 голосов
/ 14 февраля 2020

Я использую следующую функцию для запуска моих команд, которая ожидает завершения действия, но имеет время ожидания:

import os
import logging

logger = logging.getLogger()

def command_runner(command, valid_exit_codes=None, timeout=30, shell=False, decoder='utf-8'):
    """
    command_runner 2019103101
    Whenever we can, we need to avoid shell=True in order to preseve better security
    Runs system command, returns exit code and stdout/stderr output, and logs output on error
    valid_exit_codes is a list of codes that don't trigger an error
    """

    try:
        # universal_newlines=True makes netstat command fail under windows
        # timeout does not work under Python 2.7 with subprocess32 < 3.5
        # decoder may be unicode_escape for dos commands or utf-8 for powershell
        if sys.version_info >= (3, 0):
            output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=shell,
                                             timeout=timeout, universal_newlines=False)
        else:
            output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=shell,
                                             universal_newlines=False)
        output = output.decode(decoder, errors='backslashreplace')
    except subprocess.CalledProcessError as exc:
        exit_code = exc.returncode
        # noinspection PyBroadException
        try:
            output = exc.output
            try:
                output = output.decode(decoder, errors='backslashreplace')
            except Exception as subexc:
                logger.debug(subexc, exc_info=True)
                logger.debug('Cannot properly decode error. Text is %s' % output)
        except Exception:
            output = "command_runner: Could not obtain output from command."
        if exit_code in valid_exit_codes if valid_exit_codes is not None else [0]:
            logger.debug('Command [%s] returned with exit code [%s]. Command output was:' % (command, exit_code))
            if output:
                logger.debug(output)
            return exc.returncode, output
        else:
            logger.error('Command [%s] failed with exit code [%s]. Command output was:' %
                         (command, exc.returncode))
            logger.error(output)
            return exc.returncode, output
    # OSError if not a valid executable
    except OSError as exc:
        logger.error('Command [%s] faild because of OS [%s].' % (command, exc))
        return None, exc
    except subprocess.TimeoutExpired:
        logger.error('Timeout [%s seconds] expired for command [%s] execution.' % (timeout, command))
        return None, 'Timeout of %s seconds expired.' % timeout
    except Exception as exc:
        logger.error('Command [%s] failed for unknown reasons [%s].' % (command, exc))
        logger.debug('Error:', exc_info=True)
        return None, exc
    else:
        logger.debug('Command [%s] returned with exit code [0]. Command output was:' % command)
        if output:
            logger.debug(output)
        return 0, output


# YOUR CODE HERE

executable = os.path.join(os.environ['SYSTEMROOT'], 'system32', 'robocopy.exe')
mycommand = '"%s" "%s" "%s" "%s"' % (executable, source, dest, options)
result, output = command_runner(mycommand, shell=True)

...