python 程序怎么能保证只运行一个实例?第二个实例起来时发现有现有进程自动退出? - V2EX
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 11007 次点击
    这是一个创建于 3878 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在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,继续运行就可以了
    td width="10" valign="top">
    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     Solana     1628 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 16:17 PVG 00:17 LAX 08:17 JFK 11:17
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86