The full traceback for my error is:

> python zthreadtest_tjedit.py

None

Traceback (most recent call last):

File "zthreadtest_tjedit.py", line 17, in run self.function()

TypeError: 'list' object is not callable

I apologize that's this code is a bit system specific and probably won't serve as an executable example for most people. Hopefully the solution is simple enough for someone to see right off. If you're not running zfs with a currently imported zpool, but are on a *nix platform with the weir.zfs module installed, it will return an empty list with the non-threaded code enabled (see comments in code for toggling threading). With the threading module enabled, it throws the error as shown above.

Confusing to me is that the second snip of code from Jo Plaete (https://joplaete.wordpress.com/2010/07/21/threading-with-pyqt4/) runs without error, and I simply modified this code to my needs. EDIT: This error-causing difference may be related to the list object used in my code and not hers, but I still need to make mine work.

My question is: how do I resolve my error such that my threaded module runs correctly?

This seems simple, but I'm absolutely stumped. So much so that this is the first question I've posted on any help forum ever! I hope I've asked my question properly and I appreciate any help.

My Code, from much larger pyside gui program:

import PySide, sys
from PySide import QtCore, QtGui
from PySide.QtCore import *
from PySide.QtGui import *
import re, subprocess, threading
from weir import zfs

class WorkerThread(QThread):
    def __init__(self, function):
        QThread.__init__(self)
        self.function = function

    def __del__(self):
        self.wait()

    def run(self):
        self.function()
        return


class MainZ(QMainWindow):
    def __init__(self):
        super(MainZ, self).__init__()
        # print(self)
        # imported_pools = self.get_imported() # No threading
        imported_pools = self.thread_test()  # Use threading module

        print(imported_pools)

    def thread_test(self):
        self.threader = WorkerThread(self.get_imported())
        self.threader.start()

    def get_imported(self):
        pool_string = subprocess.getoutput(
            'zpool list |grep -v ^NAME.*SIZE.*ALLOC |grep -o ^[a-Z0-9]*')
        imported_pools = re.split(r'\s *', pool_string)
        return imported_pools


app = QApplication(sys.argv)
form = MainZ()
app.exec_()

Code I modeled from Jo Plaete that works for me without error:

import sys, time
from PySide import QtCore, QtGui

class GenericThread(QtCore.QThread):
 def __init__(self, function, *args, **kwargs):
  QtCore.QThread.__init__(self)
  self.function = function
  self.args = args
  self.kwargs = kwargs

 def __del__(self):
  self.wait()

 def run(self):
  self.function(*self.args,**self.kwargs)
  return

class MyApp(QtGui.QWidget):
 def __init__(self, parent=None):
  QtGui.QWidget.__init__(self, parent)
  self.setGeometry(300, 300, 280, 600)
  self.setWindowTitle('threads')
  self.layout = QtGui.QVBoxLayout(self)
  self.testButton = QtGui.QPushButton("test")
  self.connect(self.testButton, QtCore.SIGNAL("released()"), self.test)
  self.listwidget = QtGui.QListWidget(self)
  self.layout.addWidget(self.testButton)
  self.layout.addWidget(self.listwidget)

 def add(self, text):
  """ Add item to list widget """
  print("Add: " + text)
  self.listwidget.addItem(text)
  self.listwidget.sortItems()

 def addBatch(self,text="test",iters= 5,delay=0.2):
  """ Add several items to list widget """
  for i in range(iters):
   time.sleep(delay) # artificial time delay
   self.add(text+" "+str(i))

 def test(self):
  self.listwidget.clear()
  self.genericThread = GenericThread(
   self.addBatch,"from generic thread ",delay=0.3)
  self.genericThread.start()


# run
app = QtGui.QApplication(sys.argv)
test = MyApp()
test.show()
app.exec_()
1

There are 1 answers

5
NPE On BEST ANSWER

The

    self.threader = WorkerThread(self.get_imported())

should read

    self.threader = WorkerThread(self.get_imported)

When creating the thread, you want to pass the function itself and not the result of calling the function (which is a list).