PyQt4: Interrupted system call while calling commands.getoutput() in timer
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]
精彩评论