Search code examples
pythonpysidewin32comattributeerror

AttributeError - QThread and Win32com


I have a function that requires a thread, I'm using a QThread to handle it, in this function there are some win32com calls, but they are raising AttributeError.

Why is that happening and can I fix it?

Here's some code:

class MyThread(QtCore.QThread):
    def __init__(self):
        super(MyThread, self).__init__()

    def run(self):
        FB2K = foobar()
        while True:
            CurrentVolume = float(FB2K.currentVolumeLevel().strip('dB'))
            FB2K.setVolumeLevel(CurrentVolume - 0.1)
            sleep(1)


class MainFrame(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.button = QPushButton(self)
        self.thread = MyThread()
        self.button.clicked.connect(self.my_function)

    def my_function(self):
        self.thread.start()

If I run this script and click on the button it raises the AttributeError:

Traceback (most recent call last):
  File "C:/My Python Programs/foobar_acess.py", line 18, in run
    CurrentVolume = float(FB2K.currentVolumeLevel().strip('dB'))
  File "C:\Python27\pyfoobar.py", line 50, in currentVolumeLevel
    return str(playback.Settings.Volume) + "dB"
  File "C:\Python27\lib\site-packages\win32com\client\dynamic.py", line 516, in __getattr__
    raise AttributeError("%s.%s" % (self._username_, attr))
AttributeError: <unknown>.Settings

pyfoobar is a module that access foobar2000 it can set volume, catch song names and etc.

It's build around the win32com module, playback(the one raising the error) is:

playback = win32com.client.Dispatch("Foobar2000.Application.0.7")

The code under run() works fine if not run by QThread, but it freezer the UI because of the while loop.


Solution

  • Not sure why this fixed it. But here is how:

    class MyThread(QtCore.QThread):
        def __init__(self):
            super(MyThread, self).__init__()
    
        def run(self):
            import win32com.client
            import pythoncom
            pythoncom.CoInitialize()
            ProgID = "Foobar2000.Application.0.7"
            foobar_COM_object = win32com.client.Dispatch(ProgID)
            playback = foobar_COM_object.Playback
    
            while True:
                playback.Settings.Volume -= 0.1
                sleep(1)
    
    
    class MainFrame(QWidget):
        def __init__(self):
            QWidget.__init__(self)
            self.button = QPushButton(self)
            self.thread = MyThread()
            self.button.clicked.connect(self.my_function)
    
        def my_function(self):
            self.thread.start()