我正在基于irc.IRCClient和pygtk在python中开发一个irc客户端,我正在使用正确的反应器,一切正常。 现在我点击一个Url时会启动浏览器... 更好的选择是使用xdg-open运行配置的默认浏览器(在免费的桌面兼容DE中)。 在gtk按钮按下事件中选择URL。 我已经尝试了所有可能的解决方法但是我得到了100%的cpu。 下面是我尝试的各种方法,只使用reactor.spawnProcess似乎很有希望,因为直到浏览器打开一切都很好,关闭它时cpu变为100%。所有其他cpu很快就会以100%的速度跳跃并留下来。 直接启动浏览器不会更改任何内容。 我做错了什么?
python 2.6.5 - twisted 10.1.0 - pygtk 2.16.0
Marco
def on_click(self, b):
.....
.....
if data:
url = self.urls[int(data)]
# 100% cpu forever
browser = utils.getProcessValue('/usr/bin/xdg-open', [url,], os.environ)
browser.addCallback(self.printExitValue)
# 100% cpu after closing browser
xdgProcess = XDGProcessProtocol()
reactor.spawnProcess(xdgProcess, '/usr/bin/xdg-open', ['/usr/bin/xdg-open', url], os.environ )
# 100% cpu forever
os.system('xdg-open %s' % url)
# 100% cpu forever
os.spawnl(os.P_NOWAIT, '/usr/bin/xdg-open', '/usr/bin/xdg-open', url)
# 100% cpu forever
reactor.callInThread(self.browser, url)
return 0
def printExitValue(self, val):
print 'xdg-open %d' % val
def browser(self, url):
os.spawnl(os.P_NOWAIT, '/usr/bin/xdg-open', '/usr/bin/xdg-open', url)
class XDGProcessProtocol(protocol.ProcessProtocol):
def __init__(self):
self.data = ''
def connectionMade(self):
pass
def outReceived(self, data):
self.data = self.data + data
def errReceived(self, data):
self.data = self.data + data
def inConnectionLost(self):
pass
def outConnectionLost(self):
print self.data
def errConnectionLost(self):
pass
def processExited(self, reason):
print "processExited, status %d" % (reason.value.exitCode,)
def processEnded(self, reason):
print "processEnded, status %d" % (reason.value.exitCode,)
print "quitting"
def on_click(self, b):
.....
.....
if data:
url = self.urls[int(data)]
# 100% cpu forever
browser = utils.getProcessValue('/usr/bin/xdg-open', [url,], os.environ)
browser.addCallback(self.printExitValue)
# 100% cpu after closing browser
xdgProcess = XDGProcessProtocol()
reactor.spawnProcess(xdgProcess, '/usr/bin/xdg-open', ['/usr/bin/xdg-open', url], os.environ )
# 100% cpu forever
os.system('xdg-open %s' % url)
# 100% cpu forever
os.spawnl(os.P_NOWAIT, '/usr/bin/xdg-open', '/usr/bin/xdg-open', url)
# 100% cpu forever
reactor.callInThread(self.browser, url)
return 0
def printExitValue(self, val):
print 'xdg-open %d' % val
def browser(self, url):
os.spawnl(os.P_NOWAIT, '/usr/bin/xdg-open', '/usr/bin/xdg-open', url)
答案 0 :(得分:4)
关闭主题: 这是pygobject和pygtk中的一个错误,SIGCHLD处理程序进入无限循环。 这在pygobject-2.21,0和pygtk-2.17.0
中得到修复马
答案 1 :(得分:1)
您可以使用:
import webbrowser
webbrowser.open("http://www.google.it/")
答案 2 :(得分:0)
是webbrowser模块或许您正在寻找什么?它是python标准库的一部分。
答案 3 :(得分:0)
致Jan Claeys:
上面的例子,在一个gtk按钮 - 按下事件中,我从文本窗口中捕获了url(如果有的话),然后我想启动一个浏览器来打开它。
def on_click(self, b): # catch the url if url: # launch the predefined browser... return 0
上面有我试过的所有方法,除了
xdgProcess = XDGProcessProtocol() reactor.spawnProcess(xdgProcess, '/usr/bin/xdg-open', ['/usr/bin/xdg-open', url], os.environ )
执行相同操作:浏览器打开页面,但程序的cpu利用率会跳至100%并保持不变。
使用spawnProcess工作正常,但是当我关闭浏览器时,cpu跳转到100%加载。
我认为os.system和os.spawn不适合扭曲,正确的方式必须是扭曲的方式。
但似乎关闭浏览器出现问题,反应堆进入无限循环。
有任何线索吗?
注意,我不需要从生成的过程中读取或写入任何内容,也不需要关心退出状态,只需要打开URL并忘记。
马
答案 4 :(得分:0)
这是一个有效(失败)的例子。
我调整了你的irclogbot.py以在pygtk app中运行。
Sys.argv [1]是irc服务器的URL。
在方法on_click中,更改可执行路径以适合您的浏览器。
浏览器打开页面关闭后,cpu利用率跃升至100%。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2001-2009 Twisted Matrix Laboratories.
# See LICENSE for details.
import gobject
import pygtk
import gtk
# twisted imports
from twisted.internet import gtk2reactor
gtk2reactor.install()
from twisted.words.protocols import irc
from twisted.internet import reactor, protocol
from twisted.python import log
# system imports
import time, sys
class MessageLogger:
"""
An independent logger class (because separation of application
and protocol logic is a good thing).
"""
def __init__(self, file):
self.file = file
def log(self, message):
"""Write a message to the file."""
timestamp = time.strftime("[%H:%M:%S]", time.localtime(time.time()))
self.file.write('%s %s\n' % (timestamp, message))
self.file.flush()
def close(self):
self.file.close()
class LogBot(irc.IRCClient):
"""A logging IRC bot."""
nickname = "twistedbot"
def connectionMade(self):
irc.IRCClient.connectionMade(self)
self.logger = MessageLogger(open(self.factory.filename, "a"))
self.logger.log("[connected at %s]" %
time.asctime(time.localtime(time.time())))
def connectionLost(self, reason):
irc.IRCClient.connectionLost(self, reason)
self.logger.log("[disconnected at %s]" %
time.asctime(time.localtime(time.time())))
self.logger.close()
# callbacks for events
def signedOn(self):
"""Called when bot has succesfully signed on to server."""
self.join(self.factory.channel)
def joined(self, channel):
"""This will get called when the bot joins the channel."""
self.logger.log("[I have joined %s]" % channel)
def privmsg(self, user, channel, msg):
"""This will get called when the bot receives a message."""
user = user.split('!', 1)[0]
self.logger.log("<%s> %s" % (user, msg))
# Check to see if they're sending me a private message
if channel == self.nickname:
msg = "It isn't nice to whisper! Play nice with the group."
self.msg(user, msg)
return
# Otherwise check to see if it is a message directed at me
if msg.startswith(self.nickname + ":"):
msg = "%s: I am a log bot" % user
self.msg(channel, msg)
self.logger.log("<%s> %s" % (self.nickname, msg))
def action(self, user, channel, msg):
"""This will get called when the bot sees someone do an action."""
user = user.split('!', 1)[0]
self.logger.log("* %s %s" % (user, msg))
# irc callbacks
def irc_NICK(self, prefix, params):
"""Called when an IRC user changes their nickname."""
old_nick = prefix.split('!')[0]
new_nick = params[0]
self.logger.log("%s is now known as %s" % (old_nick, new_nick))
# For fun, override the method that determines how a nickname is changed on
# collisions. The default method appends an underscore.
def alterCollidedNick(self, nickname):
"""
Generate an altered version of a nickname that caused a collision in an
effort to create an unused related name for subsequent registration.
"""
return nickname + '^'
class LogBotFactory(protocol.ClientFactory):
"""A factory for LogBots.
A new protocol instance will be created each time we connect to the server.
"""
# the class of the protocol to build when new connection is made
protocol = LogBot
def __init__(self, channel, filename):
self.channel = channel
self.filename = filename
def clientConnectionLost(self, connector, reason):
"""If we get disconnected, reconnect to server."""
connector.connect()
def clientConnectionFailed(self, connector, reason):
print "connection failed:", reason
reactor.stop()
class GUI(object):
def __init__(self):
self.mw = gtk.Window()
self.mw.connect('destroy', self.quit)
bt = gtk.Button('Run browser')
bt.connect('clicked', self.on_click)
frame = gtk.Frame('Click me')
frame.add(bt)
self.mw.add(frame)
self.mw.show_all()
f = LogBotFactory('#prova', 'botlog.txt')
# connect factory to this host and port
reactor.connectTCP(sys.argv[1], 6667, f)
reactor.run()
def on_click(self, b):
url = 'http://www.gentoo.org'
xdgProcess = XDGProcessProtocol()
#####################################################
# change the executable path of the browser you have
#####################################################
reactor.spawnProcess(xdgProcess, '/usr/bin/midori', ['/usr/bin/midori', url], None)
print 'clicked'
def quit(self, w):
print 'closeapp'
try:
reactor.stop()
except:
pass
gtk.main_quit()
class XDGProcessProtocol(protocol.ProcessProtocol):
def __init__(self):
self.data = ''
def connectionMade(self):
pass
def outReceived(self, data):
self.data = self.data + data
def errReceived(self, data):
self.data = self.data + data
def inConnectionLost(self):
pass
def outConnectionLost(self):
print "outConnectionLost! The child closed their stdout!"
print self.data
def errConnectionLost(self):
pass
def processExited(self, reason):
print "processExited, status %d" % (reason.value.exitCode,)
def processEnded(self, reason):
print "processEnded, status %d" % (reason.value.exitCode,)
print "quitting"
if __name__ == '__main__':
#########################################
# sys.argv[1] is the url of the irc server
#########################################
# initialize logging
log.startLogging(sys.stdout)
GUI()
gtk.main()
马