V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
love
V2EX  ›  Python

python 程序怎么能保证只运行一个实例?第二个实例起来时发现有现有进程自动退出?

  •  
  •   love · 2015-05-15 11:56:28 +08:00 · 10318 次点击
    这是一个创建于 3462 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在linux和windows上有通用的方法吗?

    在linux上,一般都是用个lock文件来作锁,只是这种方式也有缺点,比如程序崩溃后文件没删除需要手工处理。

    PS. 以前学Windows C语言编程时Windows提供系统级锁对象,只是这是在python不好应用。
    31 条回复    2015-05-16 00:01:03 +08:00
    mahone3297
        1
    mahone3297  
       2015-05-15 12:04:35 +08:00
    》在linux上,一般都是用个lock文件来作锁,只是这种方式也有缺点,比如程序崩溃后文件没删除需要手工处理。
    好像不需要手工删除吧。。。是lock文件,不是判断文件是否存在。。。
    jun4rui
        2
    jun4rui  
       2015-05-15 12:09:20 +08:00
    自己可以写一个lock文件呗,然后每次启动看看内心里面还不是已经有一个在跑了,有就退出,没有就删掉lock。
    Septembers
        3
    Septembers  
       2015-05-15 12:10:59 +08:00   ❤️ 1
    吧PID写入lock里
    - 如果lock的PID对应进程存在 退出
    - 如果lock的PID对应进程不存在 更新PID

    如果正常运行  符合第一条 - 退出
    如果崩溃再启动 符合第二条 - 更新PID,继续运行就可以了
    noahzh
        4
    noahzh  
       2015-05-15 12:11:16 +08:00
    pid 文件就是做这件事情的。。。。
    love
        5
    love  
    OP
       2015-05-15 12:13:02 +08:00
    @mahone3297 比如说,进程起来了,发现没lock文件,就建了一个,后来程序崩溃掉了,留下一个lock文件。重启程序时发现有lock了文件了,实际没有程序在运行,这时需要手工删除这个lock文件。
    haitongz
        6
    haitongz  
       2015-05-15 12:14:19 +08:00
    love
        7
    love  
    OP
       2015-05-15 12:16:48 +08:00
    @Septembers PID是个方法,但不是完美的,因为PID会重复,总数到3万多时就重用之前的了,如果程序崩溃了,另一个程序又用到了这个pid,然后就有问题了。当然这个机会不大,但总是一个隐患。
    love
        8
    love  
    OP
       2015-05-15 12:18:37 +08:00
    @haitongz socket大法会在windows上触发防火墙对话框。
    kunimi
        9
    kunimi  
       2015-05-15 12:22:18 +08:00
    Septembers
        10
    Septembers  
       2015-05-15 12:23:01 +08:00
    Septembers
        11
    Septembers  
       2015-05-15 12:23:37 +08:00
    @kunimi 你那是对象单例
    ngloom
        12
    ngloom  
       2015-05-15 12:24:19 +08:00
    偷个懒,监听一个sock端口?
    kunimi
        13
    kunimi  
       2015-05-15 12:24:29 +08:00
    @Septembers oh,看错了~
    billlee
        14
    billlee  
       2015-05-15 12:39:00 +08:00
    在 Linux 上,正确的 lock 文件使用方法是打开 lock 文件后,用 fcntl 加锁。不是去判断文件是否存在。
    zaxaca
        15
    zaxaca  
       2015-05-15 12:40:40 +08:00
    singleton
    likuku
        16
    likuku  
       2015-05-15 12:47:44 +08:00
    Linux 上,可以查询当前进程里同文件名(py名字)进程数,

    或者直接调用shell执行ps grep wc -l 统计当前有几个进程运行,然后判断是否执行/终止 当前进程。
    kcworms
        17
    kcworms  
       2015-05-15 12:49:44 +08:00
    socket法可用,不listen的话,就算绑到gethostname()上也不会触发Windows 7的自带防火墙。或者监听localhost也行(没必要)。

    @Septembers 能说一下这个do_magic用了什么魔法吗
    mahone3297
        18
    mahone3297  
       2015-05-15 13:03:55 +08:00
    @love 说了,判断条件是canLock,不是isFileExists.....
    SoloCompany
        19
    SoloCompany  
       2015-05-15 13:11:01 +08:00 via Android
    加个守护进程(bootloader)干这事
    sujin190
        20
    sujin190  
       2015-05-15 13:28:58 +08:00
    是不是可以bind个端口
    ksc010
        21
    ksc010  
       2015-05-15 13:29:30 +08:00
    我现在用的是pid文件吧 进程id写道文件里面
    lilydjwg
        22
    lilydjwg  
       2015-05-15 13:31:04 +08:00   ❤️ 1
    我有现成的代码,适用于类 UNIX 系统,Windows 不知道: https://github.com/lilydjwg/winterpy/blob/master/pylib/pidfile.py

    用的是写有 pid 的锁文件。当然更好的办法是使用 flock。@billlee: fcntl 的锁(旧锁,不是 Linux 新加的那个)在多线程情况下会出问题的。而且我在 FreeBSD 上试过,得到了非预期的结果。

    监听套接字也是个不错的主意,还可以在这个套接字上搞搞 RPC 什么的 :-)
    lazywen
        23
    lazywen  
       2015-05-15 13:37:06 +08:00
    pid + 判断这个pid的进程、运行参数,我之前是这样搞的
    wibile
        24
    wibile  
       2015-05-15 13:44:08 +08:00
    既然有一个进程在运行,为什么还要启动第二个?我遇到的情况都是用supervisord启动程序,程序退出自动重启。
    juntao
        25
    juntao  
       2015-05-15 15:44:12 +08:00
    tabris17
        26
    tabris17  
       2015-05-15 15:59:25 +08:00
    windows下貌似不支持fcntl
    wyxfcy
        27
    wyxfcy  
       2015-05-15 16:57:00 +08:00   ❤️ 1
    @lilydjwg FreeBSD/Mac 下用 OPEN 调用加创建和加锁参数,是一个原子操作。 Linux下不支持,只能先OPEN 再 LOCK,不是原子操作。
    9hills
        28
    9hills  
       2015-05-15 17:12:25 +08:00
    @love PID重复带来的后果就是某次恰好启动不了而已。概率很小且手动处理方便

    实际上如果不是天天启动,你可能一辈子上都碰不到。
    saber000
        29
    saber000  
       2015-05-15 17:48:49 +08:00
    @lilydjwg 赞同依云的做法
    Cynic222
        30
    Cynic222  
       2015-05-15 23:38:58 +08:00
    lilydjwg
        31
    lilydjwg  
       2015-05-16 00:01:03 +08:00
    @wyxfcy 好像不是原子操作也没什么问题呀,反正锁不会被两个进程同时获取。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3113 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 13:50 · PVG 21:50 · LAX 05:50 · JFK 08:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.