如何针对 Python 运行时引入第三方包

声明

  • 本文测试所用设备系统为 Ubuntu18.04
  • 运行模式为 docker 容器模式,native 进程模式配置流程相同
  • Python 版本为 3.6,2.7 版本配置流程相同,但需要在 Python 脚本中注意语言差异
  • 模拟 MQTT client 行为的客户端为 MQTTBox
  • 本文选取 requestsPytorch 两种第三方包进行演示说明
  • 本文中基于 Hub 模块创建的服务名称为 localhub 服务。并且针对本文的测试案例中,对应的 localhub 服务、函数计算服务以及其他服务的配置统一如下:
  1. # localhub 配置
  2. # 配置文件位置: var/db/baetyl/localhub-conf/service.yml
  3. listen:
  4. - tcp://0.0.0.0:1883
  5. principals:
  6. - username: 'test'
  7. password: 'hahaha'
  8. permissions:
  9. - action: 'pub'
  10. permit: ['#']
  11. - action: 'sub'
  12. permit: ['#']
  13.  
  14. # 本地 baetyl-function-manager 配置
  15. # 配置文件位置: var/db/baetyl/function-manager-conf/service.yml
  16. hub:
  17. address: tcp://localhub:1883
  18. username: test
  19. password: hahaha
  20. rules:
  21. - clientid: localfunc-1
  22. subscribe:
  23. topic: py
  24. function:
  25. name: sayhi3
  26. publish:
  27. topic: py/hi
  28. functions:
  29. - name: sayhi3
  30. service: function-sayhi3
  31. instance:
  32. min: 0
  33. max: 10
  34. idletime: 1m
  35.  
  36. # application.yml配置
  37. # 配置文件位置: var/db/baetyl/application.yml
  38. version: v0
  39. services:
  40. - name: localhub
  41. image: hub.baidubce.com/baetyl/baetyl-hub
  42. replica: 1
  43. ports:
  44. - 1883:1883
  45. mounts:
  46. - name: localhub-conf
  47. path: etc/baetyl
  48. readonly: true
  49. - name: localhub-data
  50. path: var/db/baetyl/data
  51. - name: localhub-log
  52. path: var/log/baetyl
  53. - name: function-manager
  54. image: hub.baidubce.com/baetyl/baetyl-function-manager
  55. replica: 1
  56. mounts:
  57. - name: function-manager-conf
  58. path: etc/baetyl
  59. readonly: true
  60. - name: function-manager-log
  61. path: var/log/baetyl
  62. - name: function-sayhi3
  63. image: hub.baidubce.com/baetyl/baetyl-function-python36
  64. replica: 0
  65. mounts:
  66. - name: function-sayhi-conf
  67. path: etc/baetyl
  68. readonly: true
  69. - name: function-sayhi-code
  70. path: var/db/baetyl/function-sayhi
  71. readonly: true
  72. volumes:
  73. # hub
  74. - name: localhub-conf
  75. path: var/db/baetyl/localhub-conf
  76. - name: localhub-data
  77. path: var/db/baetyl/localhub-data
  78. - name: localhub-log
  79. path: var/db/baetyl/localhub-log
  80. # function manager
  81. - name: function-manager-conf
  82. path: var/db/baetyl/function-manager-conf
  83. - name: function-manager-log
  84. path: var/db/baetyl/function-manager-log
  85. # function python runtime sayhi
  86. - name: function-sayhi-conf
  87. path: var/db/baetyl/function-sayhi-conf
  88. - name: function-sayhi-code
  89. path: var/db/baetyl/function-sayhi-code

系统自带的 Python 环境有可能不会满足我们的需要,实际使用往往需要引入第三方库,下面给出两个示例。

引用 requests 第三方包

假定我们想要对一个网站进行爬虫,获取相应的信息。这里,我们可以引入第三方库 requests。如何引入,具体如下所示:

  • 步骤 1: 进入 Python 脚本所在目录,然后下载 requests 及其依赖(idna、urllib3、chardet、certifi),并注意 pip 命令对应 Python 的版本
  1. cd /directory/of/Python/script
  2. pip download requests
  • 步骤 2: 解压 .whl 文件,得到源码包,然后删除 .whl 文件和包描述文件,只保留源码包
  1. unzip \*.whl
  2. rm -rf *.whl *.dist-info
  • 步骤 3: 使当前目录成为一个 package
  1. touch __init__.py
  • 步骤 4: 在具体执行脚本中引入第三方库 requests,如下所示:
  1. import requests
  • 步骤 5: 执行脚本
  1. python your_script.py

如上述操作正常,则形成的脚本目录结构如下图所示。

../_images/python-third-lib-dir-requests.pngPython requests 第三方库脚本目录

下面,我们编写脚本 get.py 来获取 https://baidu.com 的 headers 信息,假定触发条件为 Python 运行时接收到来自 localhub 服务的 A 指令,具体如下:

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. import requests
  5.  
  6. def handler(event, context):
  7. """
  8. data: {"action": "A"}
  9. """
  10. if 'action' in event:
  11. if event['action'] == 'A':
  12. r = requests.get('https://baidu.com')
  13. if str(r.status_code) == '200':
  14. event['info'] = dict(r.headers)
  15. else:
  16. event['info'] = 'exception found'
  17. else: event['info'] = 'action error'
  18. else:
  19. event['error'] = 'action not found'
  20.  
  21. return event

函数运行时服务的配置如下:

  1. # python function 配置
  2. functions:
  3. - name: 'sayhi3'
  4. handler: 'get.handler'
  5. codedir: 'var/db/baetyl/function-sayhi'

如上,localhub 服务接收到发送到主题 py 的消息后,会调用 get.py 脚本执行具体处理逻辑,然后将执行结果以 MQTT 消息形式反馈给主题 py/hi。这里,我们通过 MQTTBox 订阅主题 py/hi,并向主题 py 发送消息 {"action": "A"},然后观察 MQTTBox 订阅主题 py/hi 的消息收取情况。如正常,则可正常获取 https://baidu.com 的 headers 信息。

../_images/write-python-script-third-lib-requests.png获取Baetyl官网headers信息

引用 Pytorch 第三方包

Pytorch 是机器学习中使用广泛的深度学习框架,我们可以引入第三方库 Pytorch 使用它的功能。如何引入,具体如下所示:

  • 步骤 1: 进入 Python 脚本目录,然后下载 Pytorch 及其依赖(PIL、caffee2、numpy、six、torchvision)
  1. cd /directory/of/Python/script
  2. pip3 download torch torchvision
  • 步骤 2: 解压 .whl 文件,得到源码包,然后删除 .whl 文件和包描述文件
  1. unzip \*.whl
  2. rm -rf *.whl *.dist-info
  • 步骤 3: 使当前目录成为一个 package
  1. touch __init__.py
  • 步骤 4: 在具体执行脚本中引入第三方库 Pytorch,如下所示:
  1. import torch
  • 步骤 5: 执行脚本
  1. python your_script.py

如上述操作正常,则形成的脚本目录结构如下图所示。

../_images/python-third-lib-dir-Pytorch.pngPython Pytorch 第三方库脚本目录

下面,我们编写脚本 calc.py 来使用 Pytorch 中的函数生成随机张量,假定触发条件为 Python 运行时接收到来自 localhub 服务的 B 指令,具体如下:

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. import torch
  5.  
  6. def handler(event, context):
  7. """
  8. data: {"action": "B"}
  9. """
  10. if 'action' in event:
  11. if event['action'] == 'B':
  12. x = torch.rand(5, 3)
  13. event['info'] = x.tolist()
  14. else:
  15. event['info'] = 'exception found'
  16. else:
  17. event['error'] = 'action not found'
  18.  
  19. return event

函数运行时服务的配置如下:

  1. # python function 配置
  2. functions:
  3. - name: 'sayhi3'
  4. handler: 'calc.handler'
  5. codedir: 'var/db/baetyl/function-sayhi'

如上,localhub 服务接收到发送到主题 py 的消息后,会调用 calc.py 脚本执行具体处理逻辑,然后将执行结果以 MQTT 消息形式反馈给主题 py/hi。这里,我们通过 MQTTBox 订阅主题 py/hi,并向主题 py 发送消息 {"action": "B"},然后观察 MQTTBox 订阅主题 py/hi 的消息收取情况。如正常,则可正常生成随机张量。

../_images/write-python-script-third-lib-Pytorch.png生成随机张量