Python 物联网入门指南(五)(2)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: Python 物联网入门指南(五)

Python 物联网入门指南(五)(1)https://developer.aliyun.com/article/1507233

Python 实用程序

Python 带有几个实用程序,可以与其他文件和操作系统本身进行交互。我们已经确定了我们在过去项目中使用过的所有这些 Python 实用程序。让我们讨论不同的模块及其用途,因为我们可能会在本书的最终项目中使用它们。

os 模块

正如其名称所示,这个模块(docs.python.org/3.1/library/os.html)可以与操作系统进行交互。让我们通过示例讨论一些应用。

检查文件是否存在

os模块可用于检查特定目录中是否存在文件。例如:我们广泛使用了write_file.txt文件。在打开此文件进行读取或写入之前,我们可以检查文件是否存在:

import os
if __name__ == "__main__":
    # Check if file exists
    if os.path.isfile('/home/pi/Desktop/code_samples/write_file.txt'):
        print('The file exists!')
    else:
        print('The file does not exist!')

在上述代码片段中,我们使用了os.path模块中提供的isfile()函数。当文件位置作为函数的参数传递时,如果文件存在于该位置,则返回True。在这个例子中,由于文件write_file.txt存在于代码示例目录中,该函数返回True。因此屏幕上打印出消息文件存在

if os.path.isfile('/home/pi/Desktop/code_samples/write_file.txt'): 
    print('The file exists!') 
else: 
    print('The file does not exist!')

检查文件夹是否存在

os.path.isfile()类似,还有另一个名为os.path.isdir()的函数。如果特定位置存在文件夹,则返回True。我们一直在查看位于树莓派桌面上的名为code_samples的文件夹中的所有代码示例。可以通过以下方式确认其存在:

# Confirm code_samples' existence 
if os.path.isdir('/home/pi/Desktop/code_samples'): 
    print('The directory exists!') 
else: 
    print('The directory does not exist!')

删除文件

os模块还可以使用remove()函数删除文件。将任何文件作为函数的参数传递即可删除该文件。在文件 I/O部分,我们讨论了使用文本文件read_file.txt从文件中读取。让我们通过将其作为remove()函数的参数来删除该文件:

os.remove('/home/pi/Desktop/code_samples/read_file.txt')

终止进程

可以通过将进程pid传递给kill()函数来终止在树莓派上运行的应用程序。在上一章中,我们讨论了在树莓派上作为后台进程运行的light_scheduler示例。为了演示终止进程,我们将尝试终止该进程。我们需要确定light_scheduler进程的进程pid(您可以选择由您作为用户启动的应用程序,不要触及根进程)。可以使用以下命令从命令行终端检索进程pid

ps aux

它会显示当前在树莓派上运行的进程(如下图所示)。light_scheduler应用程序的进程pid为 1815:

light_scheduler 守护程序的 PID

假设我们知道需要终止的应用程序的进程pid,让我们回顾使用kill()函数终止该函数。终止函数所需的参数包括进程pid和需要发送到进程以终止应用程序的信号(signal.SIGKILL):

import os
import signal
if __name__ == "__main__":
    #kill the application
    try:
        os.kill(1815, signal.SIGKILL)
    except OSError as error:
        print("OS Error " + str(error))

signal模块(docs.python.org/3/library/signal.html))包含表示可用于停止应用程序的信号的常量。在此代码片段中,我们使用了SIGKILL信号。尝试运行ps命令(ps aux),您会注意到light_scheduler应用程序已被终止。

监控一个进程

在前面的示例中,我们讨论了使用kill()函数终止应用程序。您可能已经注意到,我们使用了称为try/except关键字来尝试终止应用程序。我们将在下一章详细讨论这些关键字。

还可以使用try/except关键字使用kill()函数来监视应用程序是否正在运行。在介绍使用try/except关键字捕获异常的概念后,我们将讨论使用kill()函数监视进程。

os模块中讨论的所有示例都可以与本章一起下载,文件名为os_utils.py

glob 模块

glob模块(docs.python.org/3/library/glob.html)使得能够识别具有特定扩展名或特定模式的文件。例如,可以列出文件夹中的所有 Python 文件如下:

# List all files
for file in glob.glob('*.py'):
    print(file)

glob()函数返回一个包含.py扩展名的文件列表。使用for循环来遍历列表并打印每个文件。当执行前面的代码片段时,输出包含属于本章的所有代码示例的列表(输出被截断以表示):

read_from_file.py
config_parser_read.py
append_to_file.py
read_line_from_file.py
config_parser_modify.py
python_utils.py
config_parser_write.py
csv_write.py

这个模块在列出具有特定模式的文件时特别有帮助。例如:让我们考虑这样一个场景,您想要上传来自实验不同试验的文件。您只对以下格式的文件感兴趣:file1xx.txt,其中x代表09之间的任意数字。这些文件可以按以下方式排序和列出:

# List all files of the format 1xx.txt
for file in glob.glob('txt_files/file1[0-9][0-9].txt'):
    print(file)

在前面的示例中,[0-9]表示文件名可以包含09之间的任意数字。由于我们正在寻找file1xx.txt格式的文件,因此作为参数传递给glob()函数的搜索模式是file1[0-9][0-9].txt

当执行前面的代码片段时,输出包含指定格式的所有文本文件:

txt_files/file126.txt
txt_files/file125.txt
txt_files/file124.txt
txt_files/file123.txt
txt_files/file127.txt

我们找到了一篇解释使用表达式对文件进行排序的文章:www.linuxjournal.com/content/bash-extended-globbing。相同的概念可以扩展到使用glob模块搜索文件。

读者的挑战

使用glob模块讨论的例子可以与本章一起下载,文件名为glob_example.py。在其中一个例子中,我们讨论了列出特定格式的文件。你将如何列出以下格式的文件:filexxxx.*?(这里的x代表09之间的任意数字。*代表任何文件扩展名。)

shutil 模块

shutil模块(docs.python.org/3/library/shutil.html)使得可以使用move()copy()方法在文件夹之间移动和复制文件。在上一节中,我们列出了文件夹txt_files中的所有文本文件。让我们使用move()将这些文件移动到当前目录(代码执行的位置),再次在txt_files中复制这些文件,最后从当前目录中删除这些文本文件:

import glob
import shutil
import os
if __name__ == "__main__":
    # move files to the current directory
    for file in glob.glob('txt_files/file1[0-9][0-9].txt'):
        shutil.move(file, '.')
    # make a copy of files in the folder 'txt_files' and delete them
    for file in glob.glob('file1[0-9][0-9].txt'):
        shutil.copy(file, 'txt_files')
        os.remove(file)

在前面的例子中(可以与本章一起下载,文件名为shutil_example.py),文件被移动和复制,源和目的地分别作为第一个和第二个参数指定。

使用glob模块识别要移动(或复制)的文件,然后使用它们对应的方法移动或复制每个文件。

subprocess 模块

我们在上一章简要讨论了这个模块。subprocess模块(docs.python.org/3.2/library/subprocess.html)使得可以在 Python 程序内部启动另一个程序。subprocess模块中常用的函数之一是Popen。需要在程序内部启动的任何进程都需要作为列表参数传递给Popen函数:

import subprocess
if __name__ == "__main__":
    subprocess.Popen(['aplay', 'tone.wav'])

在前面的例子中,tone.wav(需要播放的 WAVE 文件)和需要运行的命令作为列表参数传递给函数。subprocess模块中还有其他几个类似用途的命令。我们留给你去探索。

sys 模块

sys模块(docs.python.org/3/library/sys.html)允许与 Python 运行时解释器进行交互。sys模块的一个功能是解析作为程序输入提供的命令行参数。让我们编写一个程序,读取并打印作为程序参数传递的文件的内容:

import sys
if __name__ == "__main__":
    with open(sys.argv[1], 'r') as read_file:
        print(read_file.read())

尝试按以下方式运行前面的例子:

python3 sys_example.py read_lines.txt

前面的例子可以与本章一起下载,文件名为sys_example.py。在运行程序时传递的命令行参数列表可以在sys模块的argv列表中找到。argv[0]通常是 Python 程序的名称,argv[1]通常是传递给函数的第一个参数。

当以read_lines.txt作为参数执行sys_example.py时,程序应该打印文本文件的内容:

I am learning Python Programming using the Raspberry Pi Zero.
This is the second line.
Line 3.
Line 4.
Line 5.
Line 6.
Line 7.

总结

在本章中,我们讨论了文件 I/O - 读取和写入文件,以及用于读取、写入和追加文件的不同标志。我们谈到了将文件指针移动到文件的不同位置以检索特定内容或在特定位置覆盖文件内容。我们讨论了 Python 中的ConfigParser模块及其在存储/检索应用程序配置参数以及读写 CSV 文件中的应用。

最后,我们讨论了在我们的项目中潜在使用的不同 Python 工具。我们将广泛使用文件 I/O 和在本书中讨论的 Python 工具。我们强烈建议在进入本书中讨论的最终项目之前,熟悉本章讨论的概念。

在接下来的章节中,我们将讨论将存储在 CSV 文件中的传感器数据上传到云端,以及记录应用程序执行过程中遇到的错误。下一章见!

第十五章:请求和 Web 框架

本章的主要内容是 Python 中的请求和 Web 框架。我们将讨论使得从 Web 检索数据(例如,获取天气更新)、将数据上传到远程服务器(例如,记录传感器数据)或控制本地网络上的设备成为可能的库和框架。我们还将讨论一些有助于学习本章核心主题的话题。

try/except关键字

到目前为止,我们已经审查并测试了所有的例子,假设程序的执行不会遇到错误。相反,应用程序有时会由于外部因素(如无效的用户输入和糟糕的互联网连接)或程序员造成的程序逻辑错误而失败。在这种情况下,我们希望程序报告/记录错误的性质,并在退出程序之前继续执行或清理资源。try/except关键字提供了一种机制,可以捕获程序执行过程中发生的错误并采取补救措施。由于可能在代码的关键部分捕获和记录错误,try/except关键字在调试应用程序时特别有用。

通过比较两个例子来理解try/except关键字。让我们构建一个简单的猜数字游戏,用户被要求猜一个 0 到 9 之间的数字:

  1. 使用 Python 的random模块生成一个随机数(在 0 到 9 之间)。如果用户猜测的数字正确,Python 程序会宣布用户为赢家并退出游戏。
  2. 如果用户输入是字母x,程序会退出游戏。
  3. 用户输入使用int()函数转换为整数。进行了一个合理性检查,以确定用户输入是否是 0 到 9 之间的数字。
  4. 整数与随机数进行比较。如果它们相同,程序会宣布用户为赢家并退出游戏。

让我们观察当我们故意向这个程序提供错误的输入时会发生什么(这里显示的代码片段可以在本章的下载中找到,文件名为guessing_game.py):

import random
if __name__ == "__main__":
    while True:
        # generate a random number between 0 and 9
        rand_num = random.randrange(0,10)
        # prompt the user for a number
        value = input("Enter a number between 0 and 9: ")
        if value == 'x':
            print("Thanks for playing! Bye!")
            break
        input_value = int(value)
        if input_value < 0 or input_value > 9:
            print("Input invalid. Enter a number between 0 and 9.")
        if input_value == rand_num:
            print("Your guess is correct! You win!")
            break
        else:
            print("Nope! The random value was %s" % rand_num)

让我们执行前面的代码片段,并向程序提供输入hello

Enter a number between 0 and 9: hello
 Traceback (most recent call last):
 File "guessing_game.py", line 12, in <module>
 input_value = int(value)
 ValueError: invalid literal for int() with base 10: 'hello'

在前面的例子中,当程序试图将用户输入hello转换为整数时失败。程序执行以异常结束。异常突出了发生错误的行。在这种情况下,它发生在第 10 行:

File "guessing_game.py", line 12, in <module>
 input_value = int(value)

异常的性质也在异常中得到了突出。在这个例子中,最后一行表明抛出的异常是ValueError

ValueError: invalid literal for int() with base 10: 'hello'

让我们讨论一个相同的例子(可以在本章的下载中找到,文件名为try_and_except.py),它使用了try/except关键字。在捕获异常并将其打印到屏幕后,可以继续玩游戏。我们有以下代码:

import random
if __name__ == "__main__":
    while True:
        # generate a random number between 0 and 9
        rand_num = random.randrange(0,10)
        # prompt the user for a number
        value = input("Enter a number between 0 and 9: ")
        if value == 'x':
            print("Thanks for playing! Bye!")
        try:
            input_value = int(value)
        except ValueError as error:
            print("The value is invalid %s" % error)
            continue
        if input_value < 0 or input_value > 9:
            print("Input invalid. Enter a number between 0 and 9.")
            continue
        if input_value == rand_num:
            print("Your guess is correct! You win!")
            break
        else:
            print("Nope! The random value was %s" % rand_num)

让我们讨论相同的例子如何使用try/except关键字:

  1. 从前面的例子中,我们知道当用户提供错误的输入时(例如,一个字母而不是 0 到 9 之间的数字),异常发生在第 10 行(用户输入转换为整数的地方),错误的性质被命名为ValueError
  2. 可以通过将其包装在try...except块中来避免程序执行的中断:
try: 
         input_value = int(value) 
      except ValueError as error:
         print("The value is invalid %s" % error)
  1. 在接收到用户输入时,程序会在try块下尝试将用户输入转换为整数。
  2. 如果发生了ValueErrorexcept块会捕获error,并将以下消息与实际错误消息一起打印到屏幕上:
except ValueError as error:
           print("The value is invalid %s" % error)
  1. 尝试执行代码示例并提供无效输入。您会注意到程序打印了错误消息(以及错误的性质),然后返回游戏循环的顶部并继续寻找有效的用户输入:
Enter a number between 0 and 9: 3
 Nope! The random value was 5
 Enter a number between 0 and 9: hello
 The value is invalid invalid literal for int() with
       base 10: 'hello'
 Enter a number between 0 and 10: 4
 Nope! The random value was 6

try...except块带来了相当大的处理成本。因此,将try...except块保持尽可能短是很重要的。因为我们知道错误发生在尝试将用户输入转换为整数的行上,所以我们将其包装在try...except块中以捕获错误。

因此,try/except关键字用于防止程序执行中的任何异常行为,因为出现错误。它使得能够记录错误并采取补救措施。与try...except块类似,还有try...except...elsetry...except...else代码块。让我们通过几个例子快速回顾一下这些选项。

try…except…else

try...except...else块在我们希望只有在没有引发异常时才执行特定代码块时特别有用。为了演示这个概念,让我们使用这个块来重写猜数字游戏示例:

try:
    input_value = int(value)
except ValueError as error:
    print("The value is invalid %s" % error)
else:
    if input_value < 0 or input_value > 9:
        print("Input invalid. Enter a number between 0 and 9.")
    elif input_value == rand_num:
        print("Your guess is correct! You win!")
        break
    else:
        print("Nope! The random value was %s" % rand_num)

使用try...except...else块修改的猜数字游戏示例可与本章一起下载,文件名为try_except_else.py。在这个例子中,程序仅在接收到有效的用户输入时才将用户输入与随机数进行比较。否则,它会跳过else块并返回到循环顶部以接受下一个用户输入。因此,当try块中的代码没有引发异常时,try...except...else被用来执行特定的代码块。

try…except…else…finally

正如其名称所示,finally块用于在离开try块时执行一块代码。即使在引发异常后,这段代码也会被执行。这在我们需要在进入下一个阶段之前清理资源和释放内存时非常有用。

让我们使用我们的猜数字游戏来演示finally块的功能。为了理解finally关键字的工作原理,让我们使用一个名为count的计数器变量,在finally块中递增,以及另一个名为valid_count的计数器变量,在else块中递增。我们有以下代码:

count = 0
valid_count = 0
while True:
  # generate a random number between 0 and 9
  rand_num = random.randrange(0,10)
  # prompt the user for a number
  value = input("Enter a number between 0 and 9: ")
  if value == 'x':
      print("Thanks for playing! Bye!")
  try:
      input_value = int(value)
  except ValueError as error:
      print("The value is invalid %s" % error)
  else:
      if input_value < 0 or input_value > 9:
          print("Input invalid. Enter a number between 0 and 9.")
          continue
      valid_count += 1
      if input_value == rand_num:
          print("Your guess is correct! You win!")
          break
      else:
          print("Nope! The random value was %s" % rand_num)
  finally:
      count += 1
print("You won the game in %d attempts "\
      "and %d inputs were valid" % (count, valid_count))

上述代码片段来自try_except_else_finally.py代码示例(可与本章一起下载)。尝试执行代码示例并玩游戏。您将注意到赢得游戏所需的总尝试次数以及有效输入的数量:

Enter a number between 0 and 9: g
 The value is invalid invalid literal for int() with
    base 10: 'g'
 Enter a number between 0 and 9: 3
 Your guess is correct! You win!
 You won the game in 9 attempts and 8 inputs were valid

这演示了try-except-else-finally块的工作原理。当关键代码块(在try关键字下)成功执行时,else关键字下的任何代码都会被执行,而在退出try...except块时(在退出代码块时清理资源时)finally关键字下的代码块会被执行。

使用先前的代码示例玩游戏时提供无效的输入,以了解代码块流程。

连接到互联网 - 网络请求

现在我们已经讨论了try/except关键字,让我们利用它来构建一个连接到互联网的简单应用程序。我们将编写一个简单的应用程序,从互联网上获取当前时间。我们将使用 Python 的requests库(requests.readthedocs.io/en/master/#)。

requests模块使得连接到网络和检索信息成为可能。为了做到这一点,我们需要使用requests模块中的get()方法来发出请求:

import requests
response = requests.get('http://nist.time.gov/actualtime.cgi')

在上述代码片段中,我们将一个 URL 作为参数传递给get()方法。在这种情况下,它是返回当前时间的 Unix 格式的 URL(en.wikipedia.org/wiki/Unix_time)。

让我们利用try/except关键字来请求获取当前时间:

#!/usr/bin/python3
import requests
if __name__ == "__main__":
  # Source for link: http://stackoverflow.com/a/30635751/822170
  try:
    response = requests.get('http://nist.time.gov/actualtime.cgi')
    print(response.text)
  except requests.exceptions.ConnectionError as error:
    print("Something went wrong. Try again")

在前面的例子中(可以与本章一起下载,命名为internet_access.py),请求是在try块下进行的,响应(由response.text返回)被打印到屏幕上。

如果在执行请求以检索当前时间时出现错误,将引发ConnectionErrorrequests.readthedocs.io/en/master/user/quickstart/#errors-and-exceptions)。这个错误可能是由于缺乏互联网连接或不正确的 URL 引起的。这个错误被except块捕获。尝试运行这个例子,它应该返回time.gov的当前时间:

<timestamp time="1474421525322329" delay="0"/>

requests 的应用-检索天气信息

让我们使用requests模块来检索旧金山市的天气信息。我们将使用OpenWeatherMap API (openweathermap.org)来检索天气信息:

  1. 为了使用 API,注册一个 API 账户并获取一个 API 密钥(免费):

来自 openweathermap.org 的 API 密钥

  1. 根据 API 文档(openweathermap.org/current),可以使用http://api.openweathermap.org/data/2.5/weather?zip=SanFrancisco&appid=API_KEY&units=imperial作为 URL 来检索一个城市的天气信息。
  2. 用你的账户的密钥替换API_KEY,并在浏览器中使用它来检索当前的天气信息。你应该能够以以下格式检索到天气信息:
{"coord":{"lon":-122.42,"lat":37.77},"weather":[{"id":800, 
       "main":"Clear","description":"clear sky","icon":"01n"}],"base": 
       "stations","main":{"temp":71.82,"pressure":1011,"humidity":50, 
       "temp_min":68,"temp_max":75.99},"wind":
       {"speed":13.04,"deg":291},
       "clouds":{"all":0},"dt":1474505391,"sys":{"type":3,"id":9966, 
       "message":0.0143,"country":"US","sunrise":1474552682, 
       "sunset":1474596336},"id":5391959,"name":"San 
       Francisco","cod":200}

天气信息(如前所示)以 JSON 格式返回。JavaScript 对象表示法JSON)是一种广泛用于在网络上传递数据的数据格式。JSON 格式的主要优点是它是一种可读的格式,许多流行的编程语言支持将数据封装在 JSON 格式中。如前面的片段所示,JSON 格式使得以可读的名称/值对交换信息成为可能。

让我们回顾一下使用requests模块检索天气并解析 JSON 数据:

  1. 用前面例子中的 URL(internet_access.py)替换为本例中讨论的 URL。这应该以 JSON 格式返回天气信息。
  2. requests 模块提供了一个解析 JSON 数据的方法。响应可以按以下方式解析:
response = requests.get(URL) 
       json_data = response.json()
  1. json()函数解析来自 OpenWeatherMap API 的响应,并返回不同天气参数(json_data)及其值的字典。
  2. 由于我们知道 API 文档中的响应格式,可以从解析后的响应中检索当前温度:
print(json_data['main']['temp'])
  1. 把所有这些放在一起,我们有这个:
#!/usr/bin/python3
       import requests
       # generate your own API key
       APP_ID = '5d6f02fd4472611a20f4ce602010ee0c'
       ZIP = 94103
       URL = """http://api.openweathermap.org/data/2.5/weather?zip={}
       &appid={}&units=imperial""".format(ZIP, APP_ID)
       if __name__ == "__main__":
         # API Documentation: http://openweathermap.org/
         current#current_JSON
         try:
           # encode data payload and post it
           response = requests.get(URL)
           json_data = response.json()
           print("Temperature is %s degrees Fahrenheit" %
           json_data['main']['temp'])
         except requests.exceptions.ConnectionError as error:
           print("The error is %s" % error)

前面的例子可以与本章一起下载,命名为weather_example.py。该例子应该显示当前的温度如下:

Temperature is 68.79 degrees Fahrenheit

requests 的应用-将事件发布到互联网

在上一个例子中,我们从互联网上检索了信息。让我们考虑一个例子,在这个例子中,我们需要在互联网上发布传感器事件。这可能是你不在家时猫门打开,或者有人踩在你家门口的地垫上。因为我们在上一章中讨论了如何将传感器与树莓派 Zero 连接,所以让我们讨论一个场景,我们可以将这些事件发布到Slack——一个工作场所通讯工具,Twitter,或者云服务,比如Phant (data.sparkfun.com/)。

在这个例子中,我们将使用requests将这些事件发布到 Slack。每当发生传感器事件,比如猫门打开时,让我们在 Slack 上给自己发送直接消息。我们需要一个 URL 来将这些传感器事件发布到 Slack。让我们回顾一下生成 URL 以将传感器事件发布到 Slack:

  1. 生成 URL 的第一步是创建一个incoming webhook。Webhook 是一种可以将消息作为有效负载发布到应用程序(如 Slack)的请求类型。
  2. 如果您是名为TeamX的 Slack 团队成员,请在浏览器中启动您团队的应用程序目录,即teamx.slack.com/apps

启动您团队的应用程序目录

  1. 在应用程序目录中搜索incoming webhooks,并选择第一个选项,Incoming WebHooks(如下截图所示):

选择 incoming webhooks

  1. 点击添加配置:

添加配置

  1. 当事件发生时,让我们向自己发送私人消息。选择 Privately to (you)作为选项,并通过单击添加 Incoming WebHooks 集成来创建一个 webhook:

选择 Privately to you

  1. 我们已经生成了一个 URL,用于发送有关传感器事件的直接消息(URL 部分隐藏):

生成的 URL

  1. 现在,我们可以使用先前提到的 URL 在 Slack 上向自己发送直接消息。传感器事件可以作为 JSON 有效负载发布到 Slack。让我们回顾一下如何将传感器事件发布到 Slack。
  2. 例如,让我们考虑在猫门打开时发布消息。第一步是为消息准备 JSON 有效负载。根据 Slack API 文档(api.slack.com/custom-integrations)),消息有效负载需要采用以下格式:
payload = {"text": "The cat door was just opened!"}
  1. 为了发布此事件,我们将使用requests模块中的post()方法。在发布时,数据有效负载需要以 JSON 格式进行编码:
response = requests.post(URL, json.dumps(payload))
  1. 将所有内容放在一起,我们有:
#!/usr/bin/python3
       import requests
       import json
       # generate your own URL
       URL = 'https://hooks.slack.com/services/'
       if __name__ == "__main__":
         payload = {"text": "The cat door was just opened!"}
         try:
           # encode data payload and post it
           response = requests.post(URL, json.dumps(payload))
           print(response.text)
         except requests.exceptions.ConnectionError as error:
           print("The error is %s" % error)
  1. 在发布消息后,请求返回ok作为响应。这表明发布成功了。
  2. 生成您自己的 URL 并执行上述示例(与本章一起提供的slack_post.py一起下载)。您将在 Slack 上收到直接消息:

在 Slack 上直接发送消息

现在,尝试将传感器接口到 Raspberry Pi Zero(在前几章中讨论),并将传感器事件发布到 Slack。

还可以将传感器事件发布到 Twitter,并让您的 Raspberry Pi Zero 检查新邮件等。查看本书的网站以获取更多示例。

Flask web 框架

在我们的最后一节中,我们将讨论 Python 中的 Web 框架。我们将讨论 Flask 框架(flask.pocoo.org/)。基于 Python 的框架使得可以使用 Raspberry Pi Zero 将传感器接口到网络。这使得可以在网络中的任何位置控制设备并从传感器中读取数据。让我们开始吧!

安装 Flask

第一步是安装 Flask 框架。可以按以下方式完成:

sudo pip3 install flask

构建我们的第一个示例

Flask 框架文档解释了构建第一个示例。根据文档修改示例如下:

#!/usr/bin/python3
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
    return "Hello World!"
if __name__ == "__main__":
    app.run('0.0.0.0')

启动此示例(与本章一起提供的flask_example.py一起下载),它应该在 Raspberry Pi Zero 上启动一个对网络可见的服务器。在另一台计算机上,启动浏览器,并输入 Raspberry Pi Zero 的 IP 地址以及端口号5000作为后缀(如下快照所示)。它应该将您带到服务器的索引页面,显示消息 Hello World!:

基于 Flask 框架的 Raspberry Pi Zero 上的 Web 服务器

您可以使用命令行终端上的ifconfig命令找到 Raspberry Pi Zero 的 IP 地址。

Python 物联网入门指南(五)(3)https://developer.aliyun.com/article/1507235

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
2月前
|
存储 数据挖掘 开发者
Python编程入门:从零到英雄
在这篇文章中,我们将一起踏上Python编程的奇幻之旅。无论你是编程新手,还是希望拓展技能的开发者,本教程都将为你提供一条清晰的道路,引导你从基础语法走向实际应用。通过精心设计的代码示例和练习,你将学会如何用Python解决实际问题,并准备好迎接更复杂的编程挑战。让我们一起探索这个强大的语言,开启你的编程生涯吧!
|
1月前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
1月前
|
机器学习/深度学习 数据可视化 数据挖掘
使用Python进行数据分析的入门指南
本文将引导读者了解如何使用Python进行数据分析,从安装必要的库到执行基础的数据操作和可视化。通过本文的学习,你将能够开始自己的数据分析之旅,并掌握如何利用Python来揭示数据背后的故事。
|
2月前
|
机器学习/深度学习 数据可视化 数据挖掘
使用Python进行数据分析的入门指南
【10月更文挑战第42天】本文是一篇技术性文章,旨在为初学者提供一份关于如何使用Python进行数据分析的入门指南。我们将从安装必要的工具开始,然后逐步介绍如何导入数据、处理数据、进行数据可视化以及建立预测模型。本文的目标是帮助读者理解数据分析的基本步骤和方法,并通过实际的代码示例来加深理解。
69 3
|
3天前
|
人工智能 编译器 Python
python已经安装有其他用途如何用hbuilerx配置环境-附带实例demo-python开发入门之hbuilderx编译器如何配置python环境—hbuilderx配置python环境优雅草央千澈
python已经安装有其他用途如何用hbuilerx配置环境-附带实例demo-python开发入门之hbuilderx编译器如何配置python环境—hbuilderx配置python环境优雅草央千澈
python已经安装有其他用途如何用hbuilerx配置环境-附带实例demo-python开发入门之hbuilderx编译器如何配置python环境—hbuilderx配置python环境优雅草央千澈
|
1月前
|
IDE 程序员 开发工具
Python编程入门:打造你的第一个程序
迈出编程的第一步,就像在未知的海洋中航行。本文是你启航的指南针,带你了解Python这门语言的魅力所在,并手把手教你构建第一个属于自己的程序。从安装环境到编写代码,我们将一步步走过这段旅程。准备好了吗?让我们开始吧!
|
1月前
|
测试技术 开发者 Python
探索Python中的装饰器:从入门到实践
装饰器,在Python中是一块强大的语法糖,它允许我们在不修改原函数代码的情况下增加额外的功能。本文将通过简单易懂的语言和实例,带你一步步了解装饰器的基本概念、使用方法以及如何自定义装饰器。我们还将探讨装饰器在实战中的应用,让你能够在实际编程中灵活运用这一技术。
39 7
|
1月前
|
开发者 Python
Python中的装饰器:从入门到实践
本文将深入探讨Python的装饰器,这一强大工具允许开发者在不修改现有函数代码的情况下增加额外的功能。我们将通过实例学习如何创建和应用装饰器,并探索它们背后的原理和高级用法。
44 5
|
1月前
|
机器学习/深度学习 人工智能 算法
深度学习入门:用Python构建你的第一个神经网络
在人工智能的海洋中,深度学习是那艘能够带你远航的船。本文将作为你的航标,引导你搭建第一个神经网络模型,让你领略深度学习的魅力。通过简单直观的语言和实例,我们将一起探索隐藏在数据背后的模式,体验从零开始创造智能系统的快感。准备好了吗?让我们启航吧!
76 3
|
1月前
|
Python
Python编程入门:从零开始的代码旅程
本文是一篇针对Python编程初学者的入门指南,将介绍Python的基本语法、数据类型、控制结构以及函数等概念。文章旨在帮助读者快速掌握Python编程的基础知识,并能够编写简单的Python程序。通过本文的学习,读者将能够理解Python代码的基本结构和逻辑,为进一步深入学习打下坚实的基础。