开发者

PyQt4: Interrupted system call while calling commands.getoutput() in timer

开发者 https://www.devze.com 2023-04-13 03:12 出处:网络
The problem appeared to be very simple, but I can not find any solution after a day of googling and looking at stackoverflow.

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: m0nochr0m开发者_如何学编程e (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.


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]
0

精彩评论

暂无评论...
验证码 换一张
取 消