当另一个python脚本运行时,如何停止我的python脚本?

时间:2015-03-30 19:41:39

标签: python linux unix

我想知道如何在已经运行的时候停止当前的python脚本。

要清楚,我想用自己的python脚本编写它。所以首先,在main方法中,它将检查我的python脚本是否已经运行。如果它正在运行,我想退出并显示错误消息。

目前我正在尝试此代码:

if os.system("ps ax | grep sample_python.py") == True:
     print "fail"
     exit(0)
else:
     print "pass"

上面的代码看起来好像是在抄袭python名称..但是它总是转到else循环而不是进入if循环并退出..

因此,出于测试目的,我运行我的脚本,并在另一个终端上再次运行我的脚本。第一个脚本不会停止,但第二个python不会进入if循环打印出错误消息。

我该如何解决这个问题?


好的,我发现了一个愚蠢的事情,我想看看是否有人可以帮我解决它.. 所以我的观点是杀死刚刚启动的python,如果另一个python当前正在运行.. 但是愚蠢的事情是..因为我正在运行我的python并在这个python中运行一个检查编码..它将一直退出..因为一旦我启动python PID将被创建并将运行... < / p>

所以.. python开始 - &gt; pid创建并运行 - &gt;检查python是否正在运行 - &gt;是的python正在运行 - &gt;出口。

我想知道是否有办法 python启动 - &gt;检查python是否已经运行 - &gt;如果正在运行则杀死当前的python而不是正在运行的python。

6 个答案:

答案 0 :(得分:7)

具有正在运行的进程的PID的锁文件是一种更系统的方法。程序只是在开始时检查PID文件是否存在并被锁定(flocklockf);如果是这样,这意味着该程序的另一个实例仍在运行。如果没有,它会创建(或重写)PID文件并将其锁定。

flock / lockf锁具有以下优点:操作系统会在程序终止时自动删除锁定。

请参阅此处如何在Python中执行此操作:

Python: module for creating PID-based lockfile?

答案 1 :(得分:0)

os.system()返回已运行命令的退出值。如果ps成功,则返回0,这不等于True。您可以显式测试命令是否返回零,这将使您进入if块。

编辑:为此需要os.subprocess。这四个命令应该得到你想要的。

p1 = subprocess.Popen(['ps', 'ax'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['grep', 'bash'], stdin=p1.stdout, stdout=subprocess.PIPE)
p3 = subprocess.Popen(['wc', '-l'], stdin=p2.stdout, stdout=subprocess.PIPE)
count = int(p3.stdout.read())
if count > 1:
    print('yes')

将“bash”替换为脚本名称。这样做是获取正在运行的进程列表,输出到grep的管道除了你的脚本(或代码示例中的bash实例)之外的所有内容,输出到wc以获取行数的管道,然后询问该进程对于它的stdout,它是当前正在运行的脚本实例的计数。然后,您可以在if语句中使用该count变量,如果有多个实例在运行,则可以中止运行。

答案 2 :(得分:0)

更多pythonic方式:

import os
import psutil

script_name = os.path.basename(__file__)
if script_name in [p.name() for p in psutil.get_process_list()]:
   print "Running"

答案 3 :(得分:0)

为什么不创建锁文件而不是grep?程序的一个实例在已知位置创建文件,并在退出时删除它。任何其他实例都必须检查该文件是否存在,并且只有在已存在的情况下才应继续运行。

os.open()函数具有以下特定标志:

import os

LOCKFILE_LOCATION = "/path/to/lockfile"

try:
    os.open(LOCKFILE_LOCATION, os.O_CREAT|os.O_WRONLY|os.O_EXCL)
    # Maybe even write the script's PID to this file, just in case you need
    # to check whether the program died unexpectedly.
except OSError:
    # File exists or could not be created. Can check errno if you really
    # need to know, but this may be OS dependent.
    print("Failed to create lockfile. Is another instance already running?")
    exit(1)
else:
    print("Pass")
    # Run the rest of the program.
    # Delete the file
    os.remove(LOCKFILE_LOCATION)

在`print(“Pass”)之后放置import time; time.sleep(20)并运行此脚本的多个实例,试试这个;除了一个之外的所有人都应该失败。

答案 4 :(得分:0)

您可以使用跨平台库psutil来循环访问进程,解析每个进程的命令行,并检查它是否是具有相同脚本路径的python进程,然后您可以在找到后停止执行只有一个杀死/停止旧实例并继续使用新实例。

import os
import psutil
import sys

for proc in psutil.process_iter():
    if "python" in proc.name():
        if len(proc.cmdline()) > 1:
            script_path = sys.argv[0]
            proc_script_path = proc.cmdline()[1]
            if script_path.startswith("." + os.sep) or script_path.startswith(".." + os.sep):
                script_path = os.path.normpath(os.path.join(os.getcwd(), script_path))
            if proc_script_path.startswith("." + os.sep) or proc_script_path.startswith(".." + os.sep):
                proc_script_path = os.path.normpath(os.path.join(proc.cwd(), proc_script_path))
            if  script_path == proc_script_path and os.getpid() != proc.pid:
                #proc.kill() # you can terminate all the other instances
                sys.exit() # or your way, terminate this newer instance here

答案 5 :(得分:-1)

因为os.system(&#34; ps ax | grep sample_python.py&#34;)返回0.这不是真的。

看看这个问题: Assign output of os.system to a variable and prevent it from being displayed on the screen

你必须写

os.popen('cat /etc/services').read() 

但是这样你总是会去#34;失败&#34;因为你的脚本已经开始了您必须计算返回行数...

在此处查看单个实例的变体:

Python: single instance of program

我写了这样的剧本。我在开始时创建了一个带有任何名称的文件,并在最后删除。这是守护程序脚本。在开始时我检查了该文件是否存在。

不错的变体就在这里Ensure a single instance of an application in Linux

import fcntl
pid_file = 'program.pid'
fp = open(pid_file, 'w')
try:
    fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
    # another instance is running
    sys.exit(1)