我想知道如何在已经运行的时候停止当前的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。
答案 0 :(得分:7)
具有正在运行的进程的PID的锁文件是一种更系统的方法。程序只是在开始时检查PID文件是否存在并被锁定(flock或lockf);如果是这样,这意味着该程序的另一个实例仍在运行。如果没有,它会创建(或重写)PID文件并将其锁定。
flock / lockf锁具有以下优点:操作系统会在程序终止时自动删除锁定。
请参阅此处如何在Python中执行此操作:
答案 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)