PyQt4:在计时器中调用commands.getoutput()时中断系统调用

发布于 2024-12-10 03:22:22 字数 4463 浏览 0 评论 0原文

问题看起来很简单,但经过一天的谷歌搜索和查看 stackoverflow 后我找不到任何解决方案。 最初我正在开发一个简单的等离子体,它将每 30 分钟向本地网络服务器发送一个特定请求,解析输出并显示在面板上的标签中。我举了一个 plasmoid 的例子 - BWC-Balance - 并对其进行了修改。这是代码:

#!/usr/bin/env python
# coding: utf-8

"""
BWC Balance plasmoid

Site: http://bitbucket.org/svartalf/bwc-balance-plasmoid/

Author: SvartalF (http://svartalf.info)
Original idea: m0nochr0me (http://m0nochr0me.blogspot.com)
"""
import re
from urllib import urlencode
import urllib2
import cookielib
import datetime
import sys
import re
import string
import os
import gobject
import commands

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyKDE4.kio import *
from PyKDE4.kdeui import *
from PyKDE4.kdecore import *
from PyKDE4.plasma import Plasma
from PyKDE4 import plasmascript
from PyKDE4.solid import Solid

from settings import SettingsDialog

parsed_ok = 0
curr_day = ''

class BWCBalancePlasmoid(plasmascript.Applet):
    """Applet main class"""

    def __init__(self, parent, args=None):
        plasmascript.Applet.__init__(self, parent)

    def init(self):
        """Applet settings"""

        self.setHasConfigurationInterface(True)
        self.setAspectRatioMode(Plasma.Square)

        self.theme = Plasma.Svg(self)
#       self.theme.setImagePath("widgets/background")
#       self.setBackgroundHints(Plasma.Applet.DefaultBackground)

        self.layout = QGraphicsLinearLayout(Qt.Horizontal, self.applet)

        # Main label with balance value
        self.label = Plasma.Label(self.applet)
        self.label.setText(u'<b><font color=blue size=3>No data...</font></b>')

        self.layout.addItem(self.label)
        self.applet.setLayout(self.layout)
        self.resize(350, 30)

        self.startTimer(2500)

    def postInit(self):
        """Start timer and do first data fetching

        Fired only if user opened access to KWallet"""

        self.setLabelText()

    def update(self, value):
        """Update label text"""

        self.label.setText(value)

    def timerEvent(self, event):
        """Create thread by timer"""

        self.setLabelText()
        pass

    def setLabelText(self):
        login = 'mylogin'

        request = 'curl --ntlm -sn http://some.local.resource'

        out_exp = ""
        out_exp = commands.getoutput(request)

        table_name_exp = re.findall(r"some_regular_expression",out_exp)

        tp =  '| html2text | grep -i -A3 ' + login


        out_exp = ''
        try:
            cmd_exp = 'curl --ntlm -sn ' + table_name_exp[0] + ' ' + tp
            out_exp = commands.getoutput(cmd_exp)
        except:
            cmd_exp = ''

        date_check = re.findall(r"one_more_regular_expression", out_exp)

        times_exp  = re.findall(r"[0-9][0-9]:[0-9][0-9]", out_exp )
        if len(times_exp) != 0 and len(date_check) != 0:
            self.label.setText(u'<b><font color=blue size=3>Start: ' + times_exp[0] + u' --- Finish: ' + str(int(string.split(times_exp[0], ':')[0]) + 9) + ':' + string.split(times_exp[0], ':')[1] + ' </span></b>')
        else:
            self.label.setText(u'<b><font color=blue size=3>No data...</span></b>')

def CreateApplet(parent):
    return BWCBalancePlasmoid(parent)

我得到的是以下错误:

# plasmoidviewer bwc-balance

plasmoidviewer(25255)/kdecore (services) KServiceFactory::findServiceByDesktopPath: "" not found
plasmoidviewer(25255)/libplasma Plasma::FrameSvg::resizeFrame: Invalid size QSizeF(0, 0) 
plasmoidviewer(25255)/libplasma Plasma::FrameSvg::resizeFrame: Invalid size QSizeF(0, 0) 

Traceback (most recent call last):
  File "/home/grekhov/.kde/share/apps/plasma/plasmoids/bwc-balance/contents/code/main.py", line 116, in timerEvent
    self.setLabelText()
  File "/home/grekhov/.kde/share/apps/plasma/plasmoids/bwc-balance/contents/code/main.py", line 146, in setLabelText
    out_exp = commands.getoutput(request)
  File "/usr/lib/python2.7/commands.py", line 50, in getoutput
    return getstatusoutput(cmd)[1]
  File "/usr/lib/python2.7/commands.py", line 60, in getstatusoutput
    text = pipe.read()
IOError: [Errno 4] Interrupted system call

正如我在谷歌搜索几个小时后所理解的那样:从管道中的读取被一些信号中断。但我唯一的信号是计时器。我发现的唯一建议是“摆脱干扰您阅读的信号”。这对我来说似乎有点奇怪和不切实际:定期读取数据而不使用计时器。 我错过了什么吗?也许应该使用其他一些机制来访问网络资源并解析其输出?或者“系统调用中断”是正常情况,应该以某种方式处理?

预先感谢您的帮助。

The problem appeared to be very simple, but I can not find any solution after a day of googling and looking at stackoverflow.
Originally I am developing a simple plasmoid which will send a specific request to local web-server every 30 minutes, parse output and display in a label on panel. I took an example of plasmoid - BWC-Balance - and modified it. Here is the code:

#!/usr/bin/env python
# coding: utf-8

"""
BWC Balance plasmoid

Site: http://bitbucket.org/svartalf/bwc-balance-plasmoid/

Author: SvartalF (http://svartalf.info)
Original idea: m0nochr0me (http://m0nochr0me.blogspot.com)
"""
import re
from urllib import urlencode
import urllib2
import cookielib
import datetime
import sys
import re
import string
import os
import gobject
import commands

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyKDE4.kio import *
from PyKDE4.kdeui import *
from PyKDE4.kdecore import *
from PyKDE4.plasma import Plasma
from PyKDE4 import plasmascript
from PyKDE4.solid import Solid

from settings import SettingsDialog

parsed_ok = 0
curr_day = ''

class BWCBalancePlasmoid(plasmascript.Applet):
    """Applet main class"""

    def __init__(self, parent, args=None):
        plasmascript.Applet.__init__(self, parent)

    def init(self):
        """Applet settings"""

        self.setHasConfigurationInterface(True)
        self.setAspectRatioMode(Plasma.Square)

        self.theme = Plasma.Svg(self)
#       self.theme.setImagePath("widgets/background")
#       self.setBackgroundHints(Plasma.Applet.DefaultBackground)

        self.layout = QGraphicsLinearLayout(Qt.Horizontal, self.applet)

        # Main label with balance value
        self.label = Plasma.Label(self.applet)
        self.label.setText(u'<b><font color=blue size=3>No data...</font></b>')

        self.layout.addItem(self.label)
        self.applet.setLayout(self.layout)
        self.resize(350, 30)

        self.startTimer(2500)

    def postInit(self):
        """Start timer and do first data fetching

        Fired only if user opened access to KWallet"""

        self.setLabelText()

    def update(self, value):
        """Update label text"""

        self.label.setText(value)

    def timerEvent(self, event):
        """Create thread by timer"""

        self.setLabelText()
        pass

    def setLabelText(self):
        login = 'mylogin'

        request = 'curl --ntlm -sn http://some.local.resource'

        out_exp = ""
        out_exp = commands.getoutput(request)

        table_name_exp = re.findall(r"some_regular_expression",out_exp)

        tp =  '| html2text | grep -i -A3 ' + login


        out_exp = ''
        try:
            cmd_exp = 'curl --ntlm -sn ' + table_name_exp[0] + ' ' + tp
            out_exp = commands.getoutput(cmd_exp)
        except:
            cmd_exp = ''

        date_check = re.findall(r"one_more_regular_expression", out_exp)

        times_exp  = re.findall(r"[0-9][0-9]:[0-9][0-9]", out_exp )
        if len(times_exp) != 0 and len(date_check) != 0:
            self.label.setText(u'<b><font color=blue size=3>Start: ' + times_exp[0] + u' --- Finish: ' + str(int(string.split(times_exp[0], ':')[0]) + 9) + ':' + string.split(times_exp[0], ':')[1] + ' </span></b>')
        else:
            self.label.setText(u'<b><font color=blue size=3>No data...</span></b>')

def CreateApplet(parent):
    return BWCBalancePlasmoid(parent)

And what I get is the following error:

# plasmoidviewer bwc-balance

plasmoidviewer(25255)/kdecore (services) KServiceFactory::findServiceByDesktopPath: "" not found
plasmoidviewer(25255)/libplasma Plasma::FrameSvg::resizeFrame: Invalid size QSizeF(0, 0) 
plasmoidviewer(25255)/libplasma Plasma::FrameSvg::resizeFrame: Invalid size QSizeF(0, 0) 

Traceback (most recent call last):
  File "/home/grekhov/.kde/share/apps/plasma/plasmoids/bwc-balance/contents/code/main.py", line 116, in timerEvent
    self.setLabelText()
  File "/home/grekhov/.kde/share/apps/plasma/plasmoids/bwc-balance/contents/code/main.py", line 146, in setLabelText
    out_exp = commands.getoutput(request)
  File "/usr/lib/python2.7/commands.py", line 50, in getoutput
    return getstatusoutput(cmd)[1]
  File "/usr/lib/python2.7/commands.py", line 60, in getstatusoutput
    text = pipe.read()
IOError: [Errno 4] Interrupted system call

As I understood after several hours of googling: reading from pipe is interrupted with some signal. But the only signal I have is timer. The only recommendation I have found is "get rid of the signal which interrupts your read". And it appears a bit strange and unrealistic for me: read data periodically without timer.
Am I missing something? Maybe there should be used some other mechanism for accessing web-resource and parsing its output? Or "Interrupted system call" is a normal situation and should be handled somehow?

Thanks in advance for help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

森林很绿却致人迷途 2024-12-17 03:22:22

看起来管道仍在读取时正在传递信号。

因此,请尝试在调用 setLabelText() 之前停止计时器,然后再重新启动计时器。

编辑

您还应该尝试重写代码以使用subprocess而不是已弃用的commands模块。例如:

pipe = subprocess.Popen(['curl', '--ntlm', '-sn', 
                         'http://some.local.resource'],
                         stdout=subprocess.PIPE)
output = pipe.communicate()[0]

It appears that a signal is being delivered whilst the pipe is still reading.

So try stopping the timer before calling setLabelText(), and then restart it again afterwards.

EDIT

You should also try rewriting your code to use subprocess instead of the deprecated commands module. For example:

pipe = subprocess.Popen(['curl', '--ntlm', '-sn', 
                         'http://some.local.resource'],
                         stdout=subprocess.PIPE)
output = pipe.communicate()[0]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文