KeyError when defining task attribute in `__init__`.
See original GitHub issueDescription of issue
This appears to be the same behavior that was reported in #886. I’m unable to use weighted task dictionarys as I get KeyError failures when trying to run. This appears to occur because I’m trying to initialize tasks inside init instead of statically when the class initalizes.
For purposes of the example below, Foo and Bar are defined directly in the class so you WOULD be able to say
class FooBarTaskSet(TaskSet):
tasks = { Foo: 1, Bar: 2 }
but in the actual code, the tasks are defined as methods on the base class. Each sub-class calls one or more of the methods in the base class to create different scenarios. So in order to be able to populate tasks, I have to use self.Foo
and in order to use self
I have to initialize the value in __init__
.
Expected behavior
As long as the tasks attribute is initialized before the class is created, I should be able to modify it however I please, and setting it in init should work the same.
Actual behavior
If tasks is set in __init__
(regardless of whether before or after calling super().__init__(...)
), you will see KeyErrors
[2019-08-19 16:58:21,786] benran6/ERROR/stderr: Traceback (most recent call last):
File "c:\python36\lib\site-packages\locust\core.py", line 358, in run
self.schedule_task(self.get_next_task())
File "c:\python36\lib\site-packages\locust\core.py", line 419, in get_next_task
return random.choice(self.tasks)
File "c:\python36\lib\random.py", line 258, in choice
return seq[i]
KeyError: 1
Environment settings
- OS: Windows
- Python version: 3.6.2
- Locust version: 0.11.0
Steps to reproduce (for bug reports)
class FooBarTaskSet(TaskSet):
def Foo(self):
print('Foo')
def Bar(self):
print('Bar')
def __init__(self, parent):
super().__init__(parent)
self.tasks = {Foo: 2, Bar: 1}
class MyLocust(HttpLocust):
host = f'https://localhost:8123'
task_set = FooBarTaskSet
min_wait = 500
max_wait = 1000
Issue Analytics
- State:
- Created 4 years ago
- Comments:5 (3 by maintainers)
Top GitHub Comments
Yeah I know, just wanted to share a use case that leads to this same issue and an implementation for the helper function you suggested
The way
TaskSet
is currently implemented, thetasks
attribute is constructed/processed within TaskSets’s meta class (TaskSetMeta
) upon class creation, and the constructed/processed result is always a list of references to callable tasks. So having a class such as:would result in the final tasks attribute to be set to
[taskA, taskB, taskB]
. This list of tasks will then be used to randomly pick tasks from.So in your case you could instead change the self.tasks to
self.tasks = [Foo, Foo, Bar]
. You could also create a helper methodset_tasks
(or something) that takes a{Task: weight}
dict and replaces the tasks attribute with a constructed list .