关于raspberry pi:如何在python中运行两个True语句?

How do I run two while True statements in python?

我正在尝试用python为我的覆盆子圆周率做一个门刷卡系统。我把程序分成两部分:一个门报警和一个刷卡记录系统。这两个程序分别工作,但如何将这两个程序组合成一个python文件?我试过穿线,但好像不行。

以下是程序:1.)门警报:如果门保持打开一定时间,LED将闪烁,然后警报响起。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import time
import RPi.GPIO as gpio

led = 37
buzzer = 11
door = 16

gpio.setmode(gpio.BOARD)
gpio.setwarnings(False)
gpio.setup(buzzer, gpio.OUT)
gpio.setup(led, gpio.OUT)
gpio.setup(door, gpio.IN, pull_up_down=gpio.PUD_UP)


def blink(buzzer):
    gpio.output(buzzer, True)
    time.sleep(0.1)
    gpio.output(buzzer, False)
    time.sleep(0.1)
    return

def blink(led):
    gpio.output(led, True)
    time.sleep(1)
    gpio.output(led, False)
    time.sleep(1)
    return

while True:
    if gpio.input(door):
        time.sleep(3)
        for i in range(0,5):
                blink(led)
        for i in range (0,5):
                blink(buzzer)
    else:
        gpio.output(buzzer, False)

gpio.cleanup()

2.)刷卡记录系统:当有人刷卡时,LED闪烁并拍照。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import datetime
import time
import os
import RPi.GPIO as gpio

led = 37
t = datetime.datetime.now()

gpio.setmode(gpio.BOARD)
gpio.setwarnings(False)
gpio.setup(led, gpio.OUT)

def blink(led):
    gpio.output(led, True)
    time.sleep(0.1)
    gpio.output(led, False)
    time.sleep(0.1)

while True:
    card = raw_input()
    f = open("Laptop Sign Out" + '.txt', 'a')
    f.write("OneCard Number:" + card[1:10] +" Time:" + t.strftime("%m-%d-%Y %H:%M:%S"))
    f.write('
'
)
    f.write(';')
    f.write('
'
)
    f.close()
    time.sleep(1)
    for i in range(0,3):
        blink(led)
    os.system('fswebcam ~/Desktop/Photos/%H%M%S.jpeg')
    time.sleep(3)

gpio.cleanup()

(更新)另外,下面是我在线程方面的尝试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import time
import RPi.GPIO as gpio
import os
import datetime
from threading import Thread

led = 37
buzzer = 11
door = 16
t = datetime.datetime.now()

gpio.setmode(gpio.BOARD)
gpio.setwarnings(False)
gpio.setup(buzzer, gpio.OUT)
gpio.setup(led, gpio.OUT)
gpio.setup(door, gpio.IN, pull_up_down=gpio.PUD_UP)


def blink(buzzer):
    gpio.output(buzzer, True)
    time.sleep(0.1)
    gpio.output(buzzer, False)
    time.sleep(0.1)
    return

def blink(led):
    gpio.output(led, True)
    time.sleep(1)
    gpio.output(led, False)
    time.sleep(1)
    return

def doorsensor():
    while True:
        if gpio.input(door):
            time.sleep(3)
            for i in range(0,5):
                    blink(led)
            for i in range (0,5):
                    blink(buzzer)
        else:
            gpio.output(buzzer, False)

def cardreader():
    while True:
        card = raw_input()
        f = open("Laptop Sign Out" + '.txt', 'a')
        f.write("OneCard Number:" + card[1:10] +" Time:" + t.strftime("%m-%d-%Y %H:%M:%S"))
        f.write('
'
)
        f.write(';')
        f.write('
'
)
        f.close()
        time.sleep(1)
        for i in range(0,3):
            blink(led)
        os.system('fswebcam ~/Desktop/Photos/%H%M%S.jpeg')
        time.sleep(3)

f1 = Thread(target = doorsensor())
f2 = Thread(target = cardreader())

f2.start()
f1.start()


gpio.cleanup()


您需要将线程函数作为target参数传递,而不是传递它们的返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import sleep

f1 = Thread(target=doorsensor) # Remove parentheses after doorsensor
f1.daemon = True
f1.start()
f2 = Thread(target=cardreader) # Remove parentheses after cardreader
f2.daemon = True
f2.start()

# Use a try block to catch Ctrl+C
try:
    # Use a while loop to keep the program from exiting and killing the threads
    while True:
        time.sleep(1.0)
except KeyboardInterrupt:
    pass

gpio.cleanup()

在每个线程上设置daemon属性,这样当只剩下守护进程线程时,程序将退出:

A thread can be flagged as a"daemon thread". The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set through the daemon property.


不管其他错误如何,一旦启动线程,就需要加入其中一个线程。

1
2
3
4
5
6
7
f1 = Thread(target = doorsensor())
f2 = Thread(target = cardreader())

f2.start()
f1.start()

f1.join()

f1.join()是做什么的?

基本上,它告诉python等到f1完成运行。如果不这样做,程序将启动f1f2,然后退出。退出后,python将释放所有资源,包括这两个线程,它们的执行将停止。


我提出了一种无线程的方法。我们的想法是把你的while实体转换成update函数,并交替调用它们。

首先,你的门环变成

1
2
3
4
5
6
7
8
9
def update_door():
    if gpio.input(door):
        time.sleep(3)
        for i in range(0,5):
                blink(led)
        for i in range (0,5):
                blink(buzzer)
    else:
        gpio.output(buzzer, False)

然后你的刷卡记录系统变成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def update_card():
    card = raw_input()
    f = open("Laptop Sign Out" + '.txt', 'a')
    f.write("OneCard Number:" + card[1:10] +" Time:" + t.strftime("%m-%d-%Y %H:%M:%S"))
    f.write('
'
)
    f.write(';')
    f.write('
'
)
    f.close()
    time.sleep(1)
    for i in range(0,3):
        blink(led)
    os.system('fswebcam ~/Desktop/Photos/%H%M%S.jpeg')
    time.sleep(3)

最后,您的主循环变成:

1
2
3
while True:
    update_door()
    update_card()

但出现了一个问题:update_card中的time.sleep也会延迟update_door。这里,您有三种解决方案:

1-如果update_door晚点可以。

好吧,好吧。

2-如果update_door延迟不好,但是如果update_card不延迟也可以

然后取下time.sleep(3)

3-你需要update_door不延误,update_card不延误。

然后,您可以使用time模块设置手动计时器。

1
2
3
4
5
6
7
lastCardUpdate = time.time()
while True:
    update_door()
    now = time.time()
    if now - lastCardUpdate >= 3:
        update_card()
        lastCardUpdate = now

update_card中的raw_input是一种阻塞方法,等待用户输入。如果您确实需要每三秒钟进行一次用户输入,那么就不能使用这种方法。如果你能把它移到while之前(即在update_card功能之外),那就没问题了。否则,您确实需要使用线程。


如果您试图同时运行这两个程序,那么您将不得不使用线程或多处理,您说您已经尝试过了。如果你有,我们可以看到你的尝试,因为我们可能会帮助你在那里的问题。

另一个问题是,所有方法都被命名为blink,这在Python中是不允许的,在Python中,所有方法都应该有不同的名称。

编辑:对于线程,请确保键入threading.Thread(target = target)作为代码。