New submission from Denver Coneybeare: The __init__() method of threading.Timer uses *mutable* default values for the "args" and "kwargs" arguments. Since the default argument objects are created once and re-used for each instance, this means that changing the args list or kwargs dict of a Timer object that used the argument defaults will specify those arguments to all future Timer objects that use the defaults too.
def __init__(self, interval, function, args=[], kwargs={}): A fully backwards-compatible way to fix this is to instead use None as the default value for args and kwargs and just create a new list and/or dict inside __init__() if they are None. That way each new instance of Timer will get its very own args list and kwargs dict object. def __init__(self, interval, function, args=None, kwargs=None): ... self.args = args if args is not None else [] self.kwargs = kwargs if kwargs is not None else {} Here is a sample script that reproduces the issue: import threading event = threading.Event() def func(*args, **kwargs): print("args={!r} kwargs={!r}".format(args, kwargs)) event.set() timer1 = threading.Timer(1, func) timer1.args.append("blah") timer1.kwargs["foo"] = "bar" timer2 = threading.Timer(1, func) timer2.start() event.wait() Here is the example output when run before the fix: c:\dev\cpython>PCbuild\python_d.exe ThreadingTimerInitDefaultArgsIssueDemo.py args=('blah',) kwargs={'foo': 'bar'} [44758 refs, 17198 blocks] And after the fix: c:\dev\cpython>PCbuild\python_d.exe ThreadingTimerInitDefaultArgsIssueDemo.py args=() kwargs={} [47189 refs, 18460 blocks] As you can see, in the version without the fix, the elements added to timer1's args and kwargs were also given to timer2, which is almost certainly not what a user would expect. A proposed patch, ThreadingTimerInitDefaultArgsIssueDemo.01.patch, is attached. This fixes the issue, updates the docs, and adds a unit test. ---------- components: Library (Lib) files: ThreadingTimerInitDefaultArgsIssueDemo.01.patch keywords: patch messages: 184278 nosy: denversc priority: normal severity: normal status: open title: threading.Timer.__init__() should use immutable argument defaults for args and kwargs type: behavior versions: Python 2.7, Python 3.1, Python 3.2, Python 3.3, Python 3.4 Added file: http://bugs.python.org/file29422/ThreadingTimerInitDefaultArgsIssueDemo.01.patch _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue17435> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com