2011-10-14 99 views
1

這個問題似乎很簡單,但是在Google搜索一天並查看了stackoverflow後,我找不到任何解決方案。 本來我正在開發一個簡單的plasmoid,它會每隔30分鐘向本地web服務器發送一個特定的請求,解析輸出並顯示在面板上的標籤上。我舉了一個plasmoid的例子 - BWC-Balance - 並對其進行了修改。下面是代碼:PyQt4:在定時器中調用commands.getoutput()時中斷系統調用

#!/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 

正如我幾個小時的谷歌搜索後明白。但我擁有的唯一信號是計時器。我發現的唯一建議是「擺脫中斷你閱讀的信號」。這對我來說似乎有點奇怪和不切實際:定期讀取數據而沒有定時器。 我錯過了什麼嗎?也許應該使用一些其他機制來訪問Web資源並解析其輸出?或者「中斷系統調用」是正常情況,應該以某種方式處理?

在此先感謝您的幫助。

+0

看起來像commands.getoutput()有一個錯誤。我用os.system()取代了它,curl將輸出保存在一個文件中,並簡單地打開該文件。工作正常。感謝ekhumoro求助。 – grekhss

回答

0

在管道仍在讀取時,看起來信號正在傳遞。

因此,請在致電setLabelText()之前嘗試停止計時器,然後再重新啓動它。

編輯

你也應該嘗試重寫代碼中使用subprocess代替過時commands模塊。例如:

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

我試圖在setLabelText()之前kill timerEvent()中的計時器 - 結果相同:中斷的系統調用。我現在什麼都不懂。最初它是一個侏儒小程序,它的工作完美,並沒有產生任何錯誤,這種奇怪的中斷......: -/ – grekhss

+0

一個有趣的事情是,閱讀一個巨大的文件不會產生任何腳本的麻煩。很奇怪。 – grekhss

+0

@grekhss。是否有可能從等式中消除等離子體,並用一個更簡單,純粹的pyqt例子重現錯誤? – ekhumoro