简体   繁体   English

为什么这个python脚本只能在Ubuntu 12.04上使用IDLE?

[英]Why does this python script only work from IDLE on Ubuntu 12.04?

Edit Written in C it works like a champ. 编辑 用C写的它就像一个冠军。 I began noticing that the python would fail unpredictably. 我开始注意到python会无法预测地失败。 The bash solution worked too but I wanted to be able to easily check if it was running so I wrote the C version so I can see it when I do a ps -e . bash解决方案也有效,但我希望能够轻松检查它是否正在运行所以我编写了C版本,所以当我做ps -e时我可以看到它。

In an attempt to address this issue and the real problem (VLC player continues to inhibit power management daemon after playback has ended) I wrote the following script. 为了解决这个问题真正的问题 (VLC播放器在播放结束后继续禁止电源管理守护进程)我编写了以下脚本。 It works when I run it from IDLE but not from terminal. 当我从IDLE运行它而不是从终端运行时,它可以工作。 My ultimate goal is to have this script run as a startup application. 我的最终目标是将此脚本作为启动应用程序运行。 I'm using Ubuntu 12.04 and Python 2.7.3. 我正在使用Ubuntu 12.04和Python 2.7.3。 What do I need to change to achieve the desired result? 我需要改变什么来达到预期的效果? Please forgive my amateur python skills. 请原谅我的业余蟒蛇技能。 Thanks in advance 提前致谢

EDIT: The script runs in terminal since I took out t.daemon = True (thanks Max Noel) however the script still doesn't run as a startup application using the command python /path/to/script/vlc_watchdog.py and also I noticed that when it is run from terminal, it only works so long as the terminal window remains open. 编辑:脚本在终端运行,因为我拿出了t.daemon = True (感谢Max Noel)但是脚本仍然没有使用命令python /path/to/script/vlc_watchdog.py和我运行作为启动应用程序运行注意到当它从终端运行时,只有终端窗口保持打开才能工作。 I want this process to go run off and be happy and free and independent of it's parent, even after the parent is closed/killed. 即使父母被关闭/被杀之后,我希望这个过程能够流下来并且快乐且自由并且独立于它的父母。 How do I make that happen? 我该如何做到这一点?

What almost worked: sudo apt-get install python-daemon ; 什么几乎工作: sudo apt-get install python-daemon ; add import daemon to the script ; import daemon添加到脚本中; move import time to the top and add time.sleep(30) immediately after ; import time移到顶部并立即添加time.sleep(30) ; do away with all the thread stuff and in it's place put with daemon.DaemonContext(): run() ; 取消所有线程的东西,并在其中放置with daemon.DaemonContext(): run() ; in the Startup Applications window of Ubuntu 12.04 add an entry that executes the command python /path/to/script/vlc_watchdog_daemon.py & . 在Ubuntu 12.04的Startup Applications窗口中添加一个执行命令python /path/to/script/vlc_watchdog_daemon.py &的条目。 That & at the end is important. 那个&最后很重要。 My best guess (and I'm a n00b at both Ubuntu and Python) is that there was something(s) that wasn't fully loaded and this not-quite-fully-loaded condition was causing the script to behave abnormally. 最好的猜测 (我在Ubuntu和Python上都是n00b)是有些东西没有完全加载,而且这种不完全加载的情况导致脚本行为异常。 That is why I added the sleep immediately following the import time and added the & at the end of the Startup Applications command. 这就是为什么我在import time立即添加了sleep并在启动应用程序命令的末尾添加了& I could have perhaps gotten away with doing less but after the headache I'm at the point where "IT WORKS DON'T TOUCH IT!!!" 我可能已经开始做更少的事情,但在头痛之后,我正处于“它的工作没有触及它!!!”的地步。 It may be possible to remove "fixes" and still get it to work. 有可能删除“修复”并仍然可以使其工作。 You the reader are welcome to try. 欢迎读者试试。 I'm good. 我很好。 Final version of script at end of question. 最终版本的脚本在问题结束时。

Original Version Didn't Quite Work as a Startup Script but works from IDLE and Terminal: 原始版本没有作为启动脚本工作,但从IDLE和终端工作:

#vlc_watchdog.py  version 0.1
import dbus
import os
import time
import subprocess
from subprocess import Popen, PIPE
from threading import Thread

def vlc_killer():
    bus = dbus.SessionBus()
    vlc_media_player_obj = bus.get_object("org.mpris.MediaPlayer2.vlc", "/org/mpris/MediaPlayer2")
    props_iface = dbus.Interface(vlc_media_player_obj, 'org.freedesktop.DBus.Properties')
    pb_stat = props_iface.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')
    if pb_stat == 'Stopped':
        os.system("kill -9 $(pidof vlc)")

def vlc_is_running():
    ps = subprocess.Popen(['ps', '-e'], stdout = PIPE)
    out, err = ps.communicate()
    for line in out.splitlines():
        if 'vlc' in line:
            return True
    return False

def run():
    while True:
        if vlc_is_running():
            vlc_killer()
        else:
            time.sleep(30)

t = Thread(target=run)
#t.daemon = True  <-- this is what broke it.  Thanks Max Noel
t.start()

Final Version Works as Intended: 最终版本按预期工作:

#!/usr/bin/env python
import time
time.sleep(30)
import dbus
import os
import subprocess
from subprocess import Popen, PIPE
import daemon
import setproctitle

sleeptime = 15

def vlc_killer():
    bus = dbus.SessionBus()
    vlc_media_player_obj = bus.get_object("org.mpris.MediaPlayer2.vlc", "/org/mpris/MediaPlayer2")
    props_iface = dbus.Interface(vlc_media_player_obj, 'org.freedesktop.DBus.Properties')
    pb_stat = props_iface.Get('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')
    if pb_stat == 'Stopped':
        os.system("kill -9 $(pidof vlc)")
    else:
        time.sleep(sleeptime)

def vlc_is_running():
    ps = subprocess.Popen(['ps', '-e'], stdout = PIPE)
    out, err = ps.communicate()
    for line in out.splitlines():
        if 'vlc' in line:
            return True
    return False

def run():
    setproctitle.setproctitle('vlc-watchdog')
    while True:
        if vlc_is_running():
            vlc_killer()
        else:
            time.sleep(sleeptime)

with daemon.DaemonContext():
    run()

Executed at startup by adding python /path/to/script/vlc_watchdog_daemon.py & to the Startup Applications window in Ubuntu 12.04. 在启动时通过将python /path/to/script/vlc_watchdog_daemon.py &添加到Ubuntu 12.04中的启动应用程序窗口来执行。 See Adding Startup Applications for detailed instructions. 有关详细说明,请参阅添加启动应用程序 I'm running Python 2.7.3. 我正在运行Python 2.7.3。

Your thread has daemon = True . 你的线程有daemon = True Your Python program will terminate as soon as the only threads left running are daemonic threads (see http://docs.python.org/2/library/threading.html#thread-objects ). 只要运行的唯一线程是守护线程,您的Python程序就会终止(请参阅http://docs.python.org/2/library/threading.html#thread-objects )。

So what's happening is that at the precise moment your t.start() call happens, your main thread reaches its end. 所以发生的事情是,在你的t.start()调用发生的确切时刻,你的主线程到达终点。 The Python VM checks what threads are left running, finds only t , which is daemonic, and terminates without executing any of the code in your run method. Python VM检查剩下的线程是什么,只查找t ,这是守护进程,并在不执行run方法中的任何代码的情况下终止。

The reason why this works in IDLE is that IDLE runs your Python code inside its own Python process, instead of spawning a new one. IDLE在IDLE中运行的原因是IDLE在自己的Python进程中运行Python代码,而不是生成一个新代码。 So when you reach the end of your code, the Python VM checks what threads are left running, finds a lot of them (non-daemonic) because there's an entire IDE still inside and doesn't terminate, so your code keeps running and kills VLC. 所以当你到达代码的末尾时,Python VM会检查剩下的线程,找到很多线程(非守护进程),因为整个IDE仍在内部并且不会终止,因此你的代码会继续运行并杀死VLC。

Furthermore, I see no need for your code to run in a separate thread (your main thread, after all, does nothing). 此外,我认为你的代码不需要在一个单独的线程中运行(你的主线程,毕竟什么都不做)。 Just do away with that entirely, and have your watchdog program simply be that while loop. 完全取消它,并让你的看门狗程序只是循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM