如何在任何时候只运行同一脚本的一个实例

时间:2018-04-03 01:19:05

标签: python windows python-3.x terminate

假设我们有一个很长的脚本:Foo.pyx
如果我执行两次,它们将同时运行。

如果我执行两次,如何终止第一个?

编辑:终止后面的那些也可以工作,我只想让一个实例随时运行。

2 个答案:

答案 0 :(得分:2)

传统的POSIX答案是使用pidfile:一个存储在一致位置的文件,该文件只保存过程的PID。

您希望存储PID的原因是,如果脚本被终止,程序的新副本将能够看到并接管,而不是错误地报告另一个副本已在运行。 (您可以使用os.kill发送0信号;如果成功,则该过程存在。)

有些库可以帮您完成并获得所有细节,但是一个简单的版本是:

import os
import sys

PIDFILE = '/var/run/myscript.pid'

def is_running():
    try:
        with open(PIDFILE) as f:
            pid = int(next(f))
        return os.kill(pid, 0)
    except Exception:
        return False

if __name__ == '__main__':
    if is_running():
        print('Another copy is already running')
        sys.exit(0)
    with open(PIDFILE, 'w') as f:
        f.write(f'{os.getpid()}\n')

您可能希望在实际代码中使用更清晰的错误处理,并且您需要考虑比赛,但我一直保持简单明了。 (如果你想真正做到这一点,你可能最好不要使用图书馆,或者自己思考所有问题,而不是从SO上复制代码。)

传统的Windows答案略有不同。在Windows上,很容易获得对退出时自动释放的文件或其他资源的强制独占锁定。事实上,这是默认情况下打开文件时会发生的事情 - 但不幸的是,这不是Python的open所发生的事情,它不会允许共享。您可以使用PyWin32中的win32api库或ctypes来调用CreateFile请求独占访问权限。如果由于文件被锁定而失败,则会运行另一个进程。

决定创建文件的位置也很重要。通常,您使用的是每用户临时目录而不是全局临时目录,这意味着每个用户可以运行一个程序副本,而不是整个系统的一个副本。

答案 1 :(得分:1)

脚本启动时,检查是否存在特定文件。一个好的名字选择是myscript.lock,但任何名字都可以。

如果存在,脚本应立即退出。否则,请创建该名称的空文件并继续执行该脚本。然后在脚本完成时删除该文件。