How to create a trigger with threading.Timer?

2019-06-13 02:38发布

I just discover python last month, I'm not a programmer at all. I'm trying to create my own software for an electronic instrument. I actually need to create a trigger which will call a function each 0.04 ms (if it's possible). I tried with this:

In my first file Metronome.py:

class Metronome:

    def __init__(self, clip, _matrix):
        self.clip = clip
        self._matrix = _matrix
        self.inc = -1


    def _trigger(self): 
        self.inc = self.inc + 1
        self._matrix.get_button(self.inc, 1).send_value(GREEN_FULL)
        t = threading.Timer(1.0, self._trigger).start()

In a second file and a new class:

I import the previous function with:

from Metronome.py import Metronome

I call the previous function with:

Metronome(self.clip, self._matrix)._trigger()

In the _trigger function, self._matrix.get_button(self.inc, 1).send_value(GREEN_FULL) allows me to send a led feedback on my instrument interface. When I launch the program, I actually get the first led feedback on my instrument. However, the others take more than 1 second to setup and some of them appear at the same time. Also, after each feedback the time of the next one is increased (like 5/10 seconde). I don't get it!

1条回答
我命由我不由天
2楼-- · 2019-06-13 03:25

apart from other issues on how the Metronome class is called (see comments above), I think the _trigger method should be more like:

def _trigger(self):
    while True:
        self.inc += 1
        self._matrix.get_button(self.inc, 1).send_value(GREEN_FULL)
        if (whatever_exit_condition):
            break
        time.sleep(time_interval_in_seconds)

if there's no exit condition, just remove the if block.

In a few words: avoid creating a new timer on every cycle. Instead, create one Timer only, when you start calling the method:

t = threading.Timer(1.0, Metronome(self.clip, self._matrix)._trigger).start()

Here is a working example on how to use the timer:

#! /usr/bin/env python
from sys import argv
import time
import threading


def f():
    retry = 0
    while True:
        print "f, retry=", retry
        retry += 1
        if retry > 3:
            break
        time.sleep(2)
    print ("f exited")


if __name__ == "__main__":
    if len(argv) <= 1:
        print "usage: %s num" % (argv[0],)
        exit(1)
    t = threading.Timer(1.0, f)
    t.start()
    for i in range(int(argv[1])):
        time.sleep(1)
        print "main, i=", i

if you run it with:

python timer.py 10

it outputs:

f, retry= 0
main, i= 0
main, i= 1
f, retry= 1
main, i= 2
main, i= 3
f, retry= 2
main, i= 4
main, i= 5
f, retry= 3
f exited
main, i= 6
main, i= 7
main, i= 8
main, i= 9

Basicallly the main thread is alive and does his thing, while the timer thread is created via the timer once and it keeps doing its bit (e.g. signal something to the user in your case), for a limited number of times (3), sleeping between each cycle. I hope it is clearer now.

查看更多
登录 后发表回答