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

时间:2014-01-17 18:32:10

标签: python ubuntu subprocess dbus

编辑 Written in C它就像一个冠军。我开始注意到python会无法预测地失败。 The bash solution也有效,但我希望能够轻松检查它是否正在运行所以我编写了C版本,以便在我ps -e时看到它。

尝试解决this issuethe real problem(VLC播放器在播放结束后继续禁止电源管理守护程序)我编写了以下脚本。当我从IDLE运行它而不是从终端运行时,它可以工作。我的最终目标是将此脚本作为启动应用程序运行。我正在使用Ubuntu 12.04和Python 2.7.3。我需要改变什么来达到预期的效果?请原谅我的业余蟒蛇技能。提前致谢

编辑:自从我拿出t.daemon = True后,脚本在终端中运行(感谢Max Noel)但是脚本仍然不能使用命令startup application运行{ {1}}并且我注意到当它从终端运行时,只有终端窗口保持打开才能工作。即使父母被关闭/被杀之后,我希望这个过程能够流下来并且快乐且自由并且独立于它的父母。我该如何做到这一点?

几乎有效: python /path/to/script/vlc_watchdog.py;将sudo apt-get install python-daemon添加到脚本中;将import daemon移至顶部,然后立即添加import time;取消所有线程的东西,放在time.sleep(30);在Ubuntu 12.04的Startup Applications窗口中添加一个执行命令with daemon.DaemonContext(): run()的条目。最后python /path/to/script/vlc_watchdog_daemon.py &很重要。我的最佳猜测(我在Ubuntu和Python上都是n00b)是有些东西没有完全加载,这个不完全加载的条件导致了脚本行为异常。这就是我在&之后立即添加sleep并在Startup Applications命令末尾添加import time的原因。我可能已经开始做更少的事情,但在头痛之后,我正处于“它的工作没有触及它!!!”的地步。有可能删除“修复”并仍然可以使其工作。欢迎读者试试。我很好。 问题末尾的最终脚本版本。

原始版本没有作为启动脚本工作,但是从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()

在启动时通过将#!/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() 添加到Ubuntu 12.04中的“启动应用程序”窗口来执行。有关详细说明,请参阅Adding Startup Applications。我正在运行Python 2.7.3。

1 个答案:

答案 0 :(得分:3)

您的帖子有daemon = True。只要运行的唯一线程是守护线程,您的Python程序就会终止(参见http://docs.python.org/2/library/threading.html#thread-objects)。

所以正在发生的事情是,在t.start()调用发生的确切时刻,您的主要线程到达终点。 Python VM会检查剩下的线程是什么,只查找t,这是守护进程,并在不执行run方法中的任何代码的情况下终止。

IDLE在IDLE中运行的原因是IDLE在自己的Python进程中运行Python代码,而不是生成一个新代码。所以当你到达代码的末尾时,Python VM会检查剩下的线程,找到很多线程(非守护进程),因为整个IDE仍在内部并且不会终止,因此你的代码会继续运行并杀死VLC。

此外,我认为你的代码不需要在一个单独的线程中运行(你的主线程,毕竟什么都不做)。完全取消它,并让你的看门狗程序只是循环。