Как завершить процесс с Python с помощью pid?

Я пытаюсь написать короткий script в python, который запустит еще один код python в подпроцессе, если еще не запущен другой конец терминала и приложения (Linux).

Так выглядит:

#!/usr/bin/python
from subprocess import Popen

text_file = open(".proc", "rb")
dat = text_file.read()
text_file.close()

def do(dat):

    text_file = open(".proc", "w")
    p = None

    if dat == "x" :

        p = Popen('python StripCore.py', shell=True)
        text_file.write( str( p.pid ) )

    else :
        text_file.write( "x" )

        p = # Assign process by pid / pid from int( dat )
        p.terminate()

    text_file.close()

do( dat )

У вас возникли проблемы с отсутствием знаний, чтобы назвать процессы pid, которое приложение читает из файла ".proc". Другая проблема заключается в том, что интерпретатор говорит, что строка с именем dat не равна "x"??? Что я пропустил?

Ответ 1

Использование awesome psutil библиотека довольно проста:

p = psutil.Process(pid)
p.terminate()  #or p.kill()

Если вы не хотите устанавливать новую библиотеку, вы можете использовать модуль os:

import os
import signal

os.kill(pid, signal.SIGTERM) #or signal.SIGKILL 

Если вы заинтересованы в запуске команды python StripCore.py, если она не запущена и в противном случае убивает ее, вы можете использовать psutil, чтобы сделать это надежно.

Что-то вроде:

import psutil
from subprocess import Popen

for process in psutil.process_iter():
    if process.cmdline() == ['python', 'StripCore.py']:
        print('Process found. Terminating it.')
        process.terminate()
        break
else:
    print('Process not found: starting it.')
    Popen(['python', 'StripCore.py'])

Пример прогона:

$python test_strip.py   #test_strip.py contains the code above
Process not found: starting it.
$python test_strip.py 
Process found. Terminating it.
$python test_strip.py 
Process not found: starting it.
$killall python
$python test_strip.py 
Process not found: starting it.
$python test_strip.py 
Process found. Terminating it.
$python test_strip.py 
Process not found: starting it.

Примечание. В предыдущих версиях psutil cmdline был атрибутом вместо метода.

Ответ 2

Я хотел сделать то же самое, что и я, но я хотел сделать это в одном файле.

Таким образом, логика будет:

  • если script с моим именем запущен, убейте его, а затем выйдите из
  • если script с моим именем не запущено, делайте что-нибудь.

Я изменил ответ Бакуриу и придумал следующее:

from os import getpid
from sys import argv, exit
import psutil  ## pip install psutil

myname = argv[0]
mypid = getpid()
for process in psutil.process_iter():
    if process.pid != mypid:
        for path in process.cmdline():
            if myname in path:
                print "process found"
                process.terminate()
                exit()

## your program starts here...

Запуск script сделает все, что делает script. Запуск другого экземпляра script приведет к уничтожению любого существующего экземпляра script.

Я использую это для отображения небольшого виджета календаря PyGTK, который запускается, когда я нажимаю часы. Если я нажму, и календарь не будет открыт, отобразится календарь. Если календарь запущен и я нажимаю часы, календарь исчезает.