2015-09-25 3 views
0

Я работаю над инструментом для ввода данных на моей работе, где он в основном принимает идентификационный номер отчета, открывает PDF-файл на эту страницу этого отчета, позволяет вам для ввода информации, а затем сохраняет ее.Python: завершить процесс и закрыть окно, открытое в (windows)

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

def get_report(id): 
    path = report_path(id) 
    if not path: 
     raise NameError 
    page = get_page(path, id) 
    proc = subprocess.Popen(["C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe", "/A", "page={}".format(page), 
          path]) 

для того, чтобы открыть отчет в Adobe Acrobat и иметь возможность ввода информации в то время как отчет остается открытым, я решил, что я должен был использовать multiprocessing. Таким образом, в результате, в основном цикле программы, где оно проходит по данным и получает идентификатор отчета, у меня есть это:

for row in rows: 
    print 'Opening report for {}'.format(ID) 
    arg = ID 
    proc = Process(target=get_report, args=(arg,)) 
    proc.start() 

    row[1] = raw_input('Enter the desired value: ') 
    rows.updateRow(row) 

    while proc.is_alive(): 
     pass 

Таким образом, можно вводить данные без программы висит на subprocess.Popen() команда. Однако, если он просто переходит к следующей записи, не закрывая окно Acrobat, которое появляется, оно фактически не откроет следующий отчет. Следовательно, while proc.is_alive():, так как он дает возможность закрыть окно вручную. Я бы , как, чтобы убить процесс сразу после нажатия «enter», и введенное значение, поэтому оно будет продолжаться и просто откроет следующий отчет с еще меньшей работой. Я пробовал несколько разных вещей, способы убить процессы через pid, используя os.kill(); Я попытался убить подпроцесс, убив сам процесс, убив их обоих, а также попытался использовать subprocess.call() вместо Popen(), чтобы узнать, не изменилось ли это.

Это не так.

Что мне здесь не хватает? Как убить процесс и закрыть окно, в котором оно было открыто? Возможно ли это? Как я уже сказал, у меня всего около 0 опыта с процессами на python. Если я делаю что-то ужасно неправильно, пожалуйста, дайте мне знать!

Заранее спасибо.

+0

Вы пробовали sys.exit (0)? –

+0

Нет, я не ... Я, наверное, неправильно понял; Я думал, что он тоже выйдет из основной программы? Я только хочу закрыть окно/процесс, порожденный как ребенок основного процесса. Будет ли это делать? – carusot42

+0

Я думаю, что неправильно понял. Вы хотите закрыть процесс Adobe Reader? –

ответ

3

Чтобы убить или завершить подпроцесс, позвоните по телефону proc.kill()/proc.terminate(). Он может оставить внукам запущенные процессы, см subprocess: deleting child processes in Windows

Таким образом, можно вводить данные без программы висит на subprocess.Popen команды().

  1. Popen() запускает команду. Он не ждет завершения команды. Существует .wait() метод и удобные функции, такие как call()
  2. Даже если Popen(command).wait() возвращается, то есть, если нарушился соответствующий внешний процесс; это не обязательно означает, что документ закрыт в общем случае (приложение для запуска запускается, но основное приложение может сохраняться).

т.е. первый шаг, чтобы отбросить ненужное multiprocessing.Process и вызвать Popen() в главном процессе вместо этого.

Второй шаг состоит в том, чтобы запустить исполняемый файл, которому принадлежит открытый документ, т. Е., если он был убит, соответствующий документ не будет оставаться открытым: AcroRd32.exe может быть уже такой программой (протестируйте его: посмотрите, ожидает ли файл call([r'..\AcroRd32.exe', ..])), или он может иметь переключатель командной строки, который допускает такое поведение. См How do I launch a file in its default program, and then close it when the script finishes?


Я попытался убить подпроцесс, убив самого процесса, убивая их обоих, а также пытались использовать subprocess.call() вместо Popen(), чтобы увидеть, если он сделал разницу.
Это не так.

Если kill() и Popen() ведут себя так же в вашем случае, то либо вы сделали ошибку (они не ведут себя так же:. Вы должны create a minimal standalone code example with a dummy pdf that demonstrates the problem описать с помощью слов: что вы ожидаете произойдет (шаг, шаг) и что происходит) или AcroRd32.exe - это просто приложение для запуска, которое я описал выше (он просто открывает документ и сразу же выходит, не дожидаясь закрытия документа).

+1

Благодарим вас за подробный отклик. Вы правы, что-то в моем коде раньше висело. Я удалил часть с помощью «многопроцессорности» и просто использовал «Popen»; Я сохранил его 'PID' как глобальную переменную в функции, которая вызывает его, и я использую' subprocess' для вызова 'TASKKILL' в этом процессе. Теперь он работает точно так, как я надеялся. Благодаря! – carusot42

+0

@ carusot42, вы запускаете 'taskkill/t', чтобы также убить дочерние процессы (по крайней мере, найти дочерние процессы, Windows не поддерживает дерево процессов, поэтому часто происходят осиротевшие процессы)? Иначе почему бы не работать 'proc.kill()'? В Windows, как правило, плохой идеей хранить PID, чтобы убить процесс. Идентификаторы процессов - это просто дескриптор процесса из таблицы дескрипторов системы, поэтому PID снова используются. 'Popen.kill' безопасен, поскольку использует дескриптор процесса. Если вам нужно 'taskkill/t', тогда сначала проверьте, что он все еще жив, т. Е.' Proc.poll() - None'. – eryksun

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