python-elgato-streamdeck icon indicating copy to clipboard operation
python-elgato-streamdeck copied to clipboard

"deckinfo" example: error at exit when executed in a function

Open twidi opened this issue 4 years ago • 2 comments

Describe the bug

When running code of "deckinfo" example in a function (instead of just in if __name__ == "__main__"), the code runs well BUT at the end, an error is displayed:

$ ./deckinfo.py 
Found 1 Stream Deck(s).

Deck 0 - Stream Deck XL.
	 - ID: 0001:0003:00
	 - Serial: 'REDACTED'
	 - Firmware Version: '1.00.007'
	 - Key Count: 32 (in a 4x8 grid)
	 - Key Images: 96x96 pixels, JPEG format, rotated 0 degrees, mirrored horizontally/vertically
Exception ignored in: <function StreamDeck.__del__ at 0x7fe3a0db0a60>
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/StreamDeck/Devices/StreamDeck.py", line 47, in __del__

And sometimes, with a core dump:

$ ./deckinfo.py
Found 1 Stream Deck(s).

Deck 0 - Stream Deck XL.
	 - ID: 0001:0003:00
	 - Serial: 'REDACTED'
	 - Firmware Version: '1.00.007'
	 - Key Count: 32 (in a 4x8 grid)
	 - Key Images: 96x96 pixels, JPEG format, rotated 0 degrees, mirrored horizontally/vertically
Exception ignored in: <function StreamDeck.__del__ at 0x7f02010f5a60>
Traceback (most recent call last):
Fatal Python error: _enter_buffered_busy: could not acquire lock for <_io.BufferedWriter name='<stderr>'> at interpreter shutdown, possibly due to daemon threads
Python runtime state: finalizing (tstate=0x195dfe0)

Current thread 0x00007f02021ae740 (most recent call first):
<no Python frame>
Aborted (core dumped)

Note that when running the example unmodified, there is no error:

$ ./deckinfo.py 
Found 1 Stream Deck(s).

Deck 0 - Stream Deck XL.
	 - ID: 0001:0003:00
	 - Serial: 'REDACTED'
	 - Firmware Version: '1.00.007'
	 - Key Count: 32 (in a 4x8 grid)
	 - Key Images: 96x96 pixels, JPEG format, rotated 0 degrees, mirrored horizontally/vertically

Also note than:

  • it does not depend on the time passed between two executions of the program
  • no threads seems to be left on the system

To Reproduce

Instead of running the code directly in if __name__ == "__main__":, call a function with the code in it:

In the deckinfo example, replace:

if __name__ == "__main__":
    streamdecks = DeviceManager().enumerate()

    print("Found {} Stream Deck(s).\n".format(len(streamdecks)))

    for index, deck in enumerate(streamdecks):
        deck.open()
        deck.reset()

        print_deck_info(index, deck)

        deck.close()

by

def main():
    streamdecks = DeviceManager().enumerate()

    print("Found {} Stream Deck(s).\n".format(len(streamdecks)))

    for index, deck in enumerate(streamdecks):
        deck.open()
        deck.reset()

        print_deck_info(index, deck)

        deck.close()

if __name__ == "__main__":
    main()
Full code
#!/usr/bin/env python3

#         Python Stream Deck Library
#      Released under the MIT license
#
#   dean [at] fourwalledcubicle [dot] com
#         www.fourwalledcubicle.com
#

# Example script that prints out information about any discovered StreamDeck
# devices to the console.

from StreamDeck.DeviceManager import DeviceManager


# Prints diagnostic information about a given StreamDeck.
def print_deck_info(index, deck):
    image_format = deck.key_image_format()

    flip_description = {
        (False, False): "not mirrored",
        (True, False): "mirrored horizontally",
        (False, True): "mirrored vertically",
        (True, True): "mirrored horizontally/vertically",
    }

    print("Deck {} - {}.".format(index, deck.deck_type()))
    print("\t - ID: {}".format(deck.id()))
    print("\t - Serial: '{}'".format(deck.get_serial_number()))
    print("\t - Firmware Version: '{}'".format(deck.get_firmware_version()))
    print("\t - Key Count: {} (in a {}x{} grid)".format(
        deck.key_count(),
        deck.key_layout()[0],
        deck.key_layout()[1]))
    print("\t - Key Images: {}x{} pixels, {} format, rotated {} degrees, {}".format(
        image_format['size'][0],
        image_format['size'][1],
        image_format['format'],
        image_format['rotation'],
        flip_description[image_format['flip']]))

def main():
    streamdecks = DeviceManager().enumerate()

    print("Found {} Stream Deck(s).\n".format(len(streamdecks)))

    for index, deck in enumerate(streamdecks):
        deck.open()
        deck.reset()

        print_deck_info(index, deck)

        deck.close()

if __name__ == "__main__":
    main()

StreamDeck Information Stream Deck XL (Firmware Version: '1.00.007')

System Information CPU: AMD threadripper OS: Ubuntu 21.04 Python: 3.9.4 python-elgato-streamdeck : 0.8.4 (installed via pip install streamdeck)

$ dpkg -l | grep libhidapi
ii  libhidapi-hidraw0:amd64                    0.10.1+dfsg-1                                                        amd64        Multi-Platform library for communication with HID devices (hidraw backend)
ii  libhidapi-libusb0:amd64                    0.10.1+dfsg-1                                                        amd64        Multi-Platform library for communication with HID devices (libusb backend)

twidi avatar May 01 '21 11:05 twidi

The problem disappears with a print or sleep at the end of the function! :open_mouth:

twidi avatar May 01 '21 11:05 twidi

Can you please re-test against 0.9.0 to determine if this issue persists?

abcminiuser avatar Jan 03 '22 07:01 abcminiuser