python - 如何组合线程?
问题描述
我正在尝试在 Raspberry Pi 上设置一个程序,该程序会将温度数据记录到 csv 作为主进程,如果温度超出范围,并行进程将发送带有时间间隔的电子邮件通知。我读到它可以用 Python 的 Threading 模块来完成,所以我正在尝试设置一个测试代码,并稍后为传感器优化它。我正在使用 random.randrange 模块进行虚拟读数,但是温度监控线程无法读取要激活的临时变量。“if”语句如何正确读取变量?
我尝试在 while True 循环之外设置 temp 并在循环后激活线程
import time
import csv
import random
import smtplib
import threading
path = 'C:/Users/saint/.PyCharmCE2019.1/config/scratches/log.csv'
templogfile = open(path,'a')
sender = 'sender@gmail.com'
receivers = ['receiver@hotmail.com']
def send_email():
while True:
print("mail module")
if temp <= 20:
try:
smtpObj = smtplib.SMTP('smtp.gmail.com', 587)
smtpObj.starttls()
smtpObj.login('sender@gmail.com', 'senderpassword')
smtpObj.sendmail(sender, receivers, message)
print("Successfully sent email")
time.sleep(15)
except smtplib.SMTPException:
print("Error: unable to send email")
time.sleep(15)
Threads = []
for i in range(1):
t = threading.Thread(target=send_email)
t.daemon = True
t.start()
with open(path,'a') as csvfile:
tempwriter = csv.writer(csvfile)
tempwriter.writerow(['Time', 'Temperature C'])
while True:
time_now = time.asctime()
temp = random.randrange(-10,20)
tempwriter.writerow([time_now, temp])
templogfile.close()
print('Time:', time_now, 'Temperature:', temp)
csvfile.flush()
time.sleep(5)
解决方案
如果您收到关于temp
未在电子邮件发送线程中定义的异常,我怀疑这是由于您正在运行的两个线程的时间问题。如果电子邮件线程在主线程第一次(模拟)温度读数之前运行,则该temp
变量将不存在。这可能会发生也可能不会发生,这取决于线程计时的确切细节,这并不总是可预测的(尽管子线程在其父线程恢复之前运行一段时间可能很常见)。
有几种方法可以解决这个问题。一个简单的解决方法是在函数的启动中添加延迟,send_email
以便运行它的线程将暂停足够长的时间,以便启动主线程中的温度读数。只需在循环sleep(1)
开始之前添加类似或类似的行。while True
另一种选择是temp
在启动电子邮件线程之前初始化为一些虚拟值。这样就会有一个变量可供读取,即使它实际上并不代表测量(或模拟)的温度。像temp = 21
放置在线程启动循环之前某处的东西可以解决问题。
但我会注意到,在这种情况下使用线程的目的并不是很清楚。电子邮件线程或多或少地对每三次温度读数进行采样,但如果这是您想要的,您可以更明确地执行此操作。如果您不想以传感器循环的全速发送垃圾邮件,您还可以检查每个读数,并仅以更有限的速率发送电子邮件。我会考虑这样的事情:
email_flag = False
count = 0
while True:
time_now = time.asctime()
temp = random.randrange(-10,20)
tempwriter.writerow([time_now, temp])
if temp <= 20:
email_flag = True
count += 1
if email_flag and count >= 3:
send_email() # unconditionally sends the message
email_flag = False
count = 0
推荐阅读
- go - gocql Query.Get() 与 Query.GetRelease()
- css - svg模糊效果,设置特定颜色
- python - 安装 Python 3.6.5 但在 Docker 中获得了 Python 3.6.6
- php - 多个登录页面模板php
- codeigniter - 为什么通过控制器重定向时出现状态码 303
- javascript - php echoed html中的Textarea无法正确发布值
- elgg - 如何在 elgg 上创建自动博客文章
- c++ - 了解 Linux 虚拟内存:valgrind 的 massif 输出显示了使用和不使用 --pages-as-heap 的主要区别
- bash - LEDE 中的 Bash shell 混淆器
- visual-studio - Visual Studio:调试器以第 16 个数字系统显示数字