define type of queue items in python
Question:
I have a function with a queue.Queue
as an argument. This queue contains elements of my self defined class PlantCommand
and should be processed by another thread.
Therefor, I defined the thread target function in the following way:
def run(command_queue: queue.Queue, status: PlantStatus) -> None:
When I now remove one item from the queue using its get()
-function, the type of the element is not known anymore. Is there a way to define the type of the queue items? Something like
def run(command_queue: queue.Queue<PlantCommand>, status: PlantStatus) -> None:
Or can I define the item type afterwards?
I often use the auto completition and also check my code using the syntax highlighting. And in the case of missing type information, it doesn’t work anymore. I.e. when I type in _cmd.
I get no suggestions related to the PlantCommand
-class of the items, that I put into the queue.
class PlantCommand():
NO_CMD = 0
ENABLE_REMOTE_CONTROL = 1
RUN_NC_SCRIPT = 2
ABORT = 3
TERMINATE = 4
_valid_commands = (NO_CMD,
ENABLE_REMOTE_CONTROL,
RUN_NC_SCRIPT,
ABORT,
TERMINATE)
def __init__(self, command: int = NO_CMD, file: str = '') -> None:
if command not in PlantCommand._valid_commands:
raise ValueError('No valid command.')
self.command = command
self.file = file
def run(command_queue: queue.Queue, status: PlantStatus) -> None:
logging.debug('Plant thread started.')
# statemachine
while True:
try:
_cmd = command_queue.get_nowait()
if _cmd.command == PlantCommand.TERMINATE:
pass
except queue.Empty:
# no item in queue -> continue
pass
Answers:
Just use proper Python syntax for typing container items:
def run(command_queue: queue.Queue[int], status: PlantStatus) -> None:
...
Since you are new to the language, keep in mind that typing is optional and only requested by the tooling that surrounds your development stage: if you ever get to a situation where proper typing would be too complicated, you can always just ignore it altogether.
(in time: this syntax is implemented for queue.Queue
from Python 3.9 onwards)
This is documented here: https://docs.python.org/3.9/library/stdtypes.html#types-genericalias – although the documentation only uses examples of the built-in types, other collections defined in Python’s stdlib also work that way. The full reasoning and implementation is described on PEP 585 – https://peps.python.org/pep-0585/ . Support for this even comes for free if one implements their collection classes inheriting from the appropriate abstract base classes in collections.abc
.
Nonetheless, regardless of being able to find the proper documentation for typing something, keep in mind that Typing expressions following the :
must be valid ("classic") Python expressions themselves. So the <
and >
symbos are only used as operators in the language, and never as brackets – and since the language could actually make use of the [
and ]
for classes even before any language changes were made to support it (as operator overloading for classes would already work since Python 2.2, and it was just a matter of defining how [ ]
indexing would work for classes), those were adopted.
I have a function with a queue.Queue
as an argument. This queue contains elements of my self defined class PlantCommand
and should be processed by another thread.
Therefor, I defined the thread target function in the following way:
def run(command_queue: queue.Queue, status: PlantStatus) -> None:
When I now remove one item from the queue using its get()
-function, the type of the element is not known anymore. Is there a way to define the type of the queue items? Something like
def run(command_queue: queue.Queue<PlantCommand>, status: PlantStatus) -> None:
Or can I define the item type afterwards?
I often use the auto completition and also check my code using the syntax highlighting. And in the case of missing type information, it doesn’t work anymore. I.e. when I type in _cmd.
I get no suggestions related to the PlantCommand
-class of the items, that I put into the queue.
class PlantCommand():
NO_CMD = 0
ENABLE_REMOTE_CONTROL = 1
RUN_NC_SCRIPT = 2
ABORT = 3
TERMINATE = 4
_valid_commands = (NO_CMD,
ENABLE_REMOTE_CONTROL,
RUN_NC_SCRIPT,
ABORT,
TERMINATE)
def __init__(self, command: int = NO_CMD, file: str = '') -> None:
if command not in PlantCommand._valid_commands:
raise ValueError('No valid command.')
self.command = command
self.file = file
def run(command_queue: queue.Queue, status: PlantStatus) -> None:
logging.debug('Plant thread started.')
# statemachine
while True:
try:
_cmd = command_queue.get_nowait()
if _cmd.command == PlantCommand.TERMINATE:
pass
except queue.Empty:
# no item in queue -> continue
pass
Just use proper Python syntax for typing container items:
def run(command_queue: queue.Queue[int], status: PlantStatus) -> None:
...
Since you are new to the language, keep in mind that typing is optional and only requested by the tooling that surrounds your development stage: if you ever get to a situation where proper typing would be too complicated, you can always just ignore it altogether.
(in time: this syntax is implemented for queue.Queue
from Python 3.9 onwards)
This is documented here: https://docs.python.org/3.9/library/stdtypes.html#types-genericalias – although the documentation only uses examples of the built-in types, other collections defined in Python’s stdlib also work that way. The full reasoning and implementation is described on PEP 585 – https://peps.python.org/pep-0585/ . Support for this even comes for free if one implements their collection classes inheriting from the appropriate abstract base classes in collections.abc
.
Nonetheless, regardless of being able to find the proper documentation for typing something, keep in mind that Typing expressions following the :
must be valid ("classic") Python expressions themselves. So the <
and >
symbos are only used as operators in the language, and never as brackets – and since the language could actually make use of the [
and ]
for classes even before any language changes were made to support it (as operator overloading for classes would already work since Python 2.2, and it was just a matter of defining how [ ]
indexing would work for classes), those were adopted.