2013-04-24 2 views
4

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

Я пробовал приведенный ниже код, и это не выход. Я попытался посмотреть, могу ли я заставить wait() работать, но также не повезло.

Любые идеи? работает питон 2,7

EDIT: Я хочу, чтобы скрипт для запуска команды :)

  p = subprocess.Popen('unrar e ' + root + '/' + i + ' ' + testfolder, 
           bufsize=2048, shell=True, 
           stdin=subprocess.PIPE) 
      p.stdin.write('e') 
      p.communicate() 

for root, dirs, files in os.walk(testfolder): 
    for i in files: 

     print 'Deleting rar files' 
     os.remove(i) 

for i in os.listdir(testfolder): 
    if os.path.isdir(testfolder + i): 
     shutil.rmtree(testfolder + i) 
+0

если вы ждете команды, вам не нужно 'subprocess' –

+0

Я хотел бы, чтобы мой сценарий запуска команды. –

+0

'os.system (« some command »)' блокирует afaik .... поэтому он должен блокироваться, пока unrar не вернется хотя бы (что я предполагаю, когда он закончен) ... хотя я бы подумал, что subproccess.communicate также блокировка ... Мое предположение заключается в том, что unrar не ждет, пока его закончит, чтобы вернуть код выхода –

ответ

1

Вашей проблема ждет на подпроцессе, или делать вещи в порядке (то есть распаковка, то удаление).

Если ваша проблема ждет на подпроцесс, то вы должны проверить функция subprocess.call

Проверить:

http://docs.python.org/2/library/subprocess.html#module-subprocess

Эта функция блокируется, пока другой процесс не завершится.

Если ваша проблема, однако, распаковка файлов, и вы не necesarrily должны использовать subprocessess, то просто проверить любой другой LIB для распаковки, как pyunrar2:

или это еще один:

+0

Моя проблема в том, что я хочу, чтобы он сначала распаковывал, а затем удалял файлы. прямо сейчас он переходит к удалению файлов, прежде чем он сможет закончить распаковку. –

+0

, то просто используйте 'subprocess.call()' вместо 'subprocess.Popen' –

+0

@ vlad-ardelean Использование' subprocess.call() 'несовместимо с необходимостью записи символа в stdin команды, как это делает исходный код. –

5

Это зло:

p = subprocess.Popen('unrar e ' + root + '/' + i + ' ' + testfolder, 
     bufsize=2048, shell=True, stdin=subprocess.PIPE) 

Вместо

p = subprocess.Popen(['unrar', 'e', '%s/%s' % (root, i), testfolder], 
     bufsize=2048, stdin=subprocess.PIPE) 
p.stdin.write('e') 
p.wait() 
if p.returncode == 0: 
    pass # put code that must only run if successful here. 

Пропустив точный массив, а не строки в Popen и не используя shell=True, имя файла с пробелом в нем не может быть интерпретируется как более чем один аргумент, или команда подоболочки, или какая-либо другая потенциально вредоносная вещь (подумайте о файле с $(rm -rf ..) в его названии).

Затем, после вызова p.wait() (нет необходимости в p.communicate(), когда вы не захватывая поток ошибок или стандартный вывод), вы должны проверить p.returncode, чтобы определить, был ли процесс успешным, и только приступить к удалить файлы, если p.returncode == 0 (с указанием успеха).

Ваш первоначальный диагноз, что p.communicate() возвращается, пока процесс unrar все еще работает, не представляется возможным; p.communicate() и p.wait() не работает так же.


Если перебегая ssh, это изменяет немного:

import pipes # in Python 2.x; in 3.x, use shlex.quote() instead 
p = subprocess.Popen(['ssh', ' '.join(
     [pipes.quote(s) for s in ['unrar', 'e', '%s/%s' % (root, i), testfolder]]) 
+1

Возможно, вам понадобится 'p.stdin.close()' перед 'p.wait()', иначе, если ваша программа ждет EOF, ваш код будет висеть в ожидании подпроцесса. – Michael

+0

Кроме того, если подпроцесс является 'ssh', я вижу, что даже используя вторую форму, мне все равно приходится добавлять кавычки вокруг аргументов с пробелами, иначе удаленная система не видит их как один аргумент. – Michael

+0

@ Майкл, ssh делает удаленный раунд расширения в дополнение к локальному расширению, который с помощью этой техники правильно избегает. Если вы хотите подготовить команды для ssh, используйте 'pipe.quote()' (или, в Python 3.x, 'shlex.quote()'), чтобы избежать ваших аргументов. –

Смежные вопросы