惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
罗磊的独立博客
人人都是产品经理
人人都是产品经理
博客园_首页
Hugging Face - Blog
Hugging Face - Blog
美团技术团队
L
Lohrmann on Cybersecurity
博客园 - 【当耐特】
量子位
Last Week in AI
Last Week in AI
D
Darknet – Hacking Tools, Hacker News & Cyber Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
Cyber Attacks, Cyber Crime and Cyber Security
腾讯CDC
有赞技术团队
有赞技术团队
Cyberwarzone
Cyberwarzone
T
Tor Project blog
V
V2EX
L
LINUX DO - 热门话题
Security Latest
Security Latest
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
NISL@THU
NISL@THU
C
Cisco Blogs
T
Tailwind CSS Blog
G
GRAHAM CLULEY
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - Franky
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
小众软件
小众软件
K
Kaspersky official blog
博客园 - 司徒正美
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
Jina AI
Jina AI
S
Schneier on Security
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Exploit Database - CXSecurity.com
Scott Helme
Scott Helme
J
Java Code Geeks
博客园 - 聂微东
Martin Fowler
Martin Fowler
MongoDB | Blog
MongoDB | Blog
AWS News Blog
AWS News Blog
Know Your Adversary
Know Your Adversary
C
Cybersecurity and Infrastructure Security Agency CISA
F
Fortinet All Blogs
T
Threat Research - Cisco Blogs
C
CXSECURITY Database RSS Feed - CXSecurity.com
雷峰网
雷峰网

Nemo

再见,2025 Complete ORB-SLAM3 Setup Guide for Jetson Xavier NX with RealSense D455 20250723 再见,2024 Using CertBot for Automatic Secure EMQX Broker Create Your Own GPS Data Publisher Support SSL AGV Dispatching System Technical Documentation Finding Nemo No title 香港賽馬會呈獻系列:黑白——攝影敘事 再见,2023 团团是只猫 Design an FSM for Robot State Machines – Basics of Computer Science Data-driven robot lifespan: Collection 数据驱动的机器人寿命:收集、诊断、预测 Exploring the design space of binary search trees 特首来了 Large language models, explained with a minimum of math and jargon 设计有缓存异步逻辑的监控脚本并测试其资源占用 在vscode的Dev Container中构建.NET开发环境及使用doxygen和graphviz绘制函数调用图 State or Status? A*算法两种时间复杂度 /A* Algorithm: Two Types of Time Complexity 使用KD-Tree快速收敛到最近坐标点/Fast convergence to the nearest coordinate point using KD-Tree 翻译 || 总结 - Go语言中的空结构体(The empty struct) 再见,2022 从PE工作报告中能读出什么 Give me miles, give me truth AMR调度系统性能优化/AMR Dispatch System Performance Optimization 条件触发AMR避让流程/Conditionally triggered AMR avoidance process Docker实现调度系统整体部署/Docker implementation of dispatching system overall deployment 调度系统中加密算法的使用/增加SM4补0方法/Use of encryption algorithms in scheduling systems/add SM4 complementary 0 method 一篇关于北京四天三夜的攻略 2022 藏疆自驾 策划/招募书 AMR仿真模型/AMR Simulation Model 东东有鱼2022年会分享 使用perf-FlameGraph监控系统性能 Beyond Compare 4删除试用 你的灵魂有香气 Pyinstaller打包Python项目 [转载]Python中的单例模式的几种实现方式的及优化 - Nemo 再见! 2020 1024 UML软件建模 入职优必选一个月 写论文时 那些让你开心的软件 - Nemo 分享一个记录刷题次数的模版 LeetCode-查找表类算法题精析 PyCharm 调用vs 2010 C++库导致提示报错R6034解决方法 MySQL基础教程 多种数据结构的Python实现形式 字节跳动-挑战字符串 选择排序 二分查找和大O表示法 算法中的动态规划问题 高高手课程-青山裕企人像摄影 笔记(内含福利)
使用loguru记录串口数据并使用Docker搭建ARM开发环境
Nemo · 2023-05-31 · via Nemo

背景

开发过程中需要记录机器人串口发送的数据,就想到之前体验感很好的loguru,就想着继续用它做一个:

  • 可以定期、定量、动作触发打包压缩,
  • 日志等级分类
  • 配置简单
  • 占用资源低

的机器人本体日志记录的系统,同时也要有很好的功能扩展性,后期扩展功能方便等

loguru配置

loguru是最早开发AMR调度系统发现的,比起去大量自定义logging,实在是太方便了,同时也是异步的,不会阻塞当前逻辑。

可以按照官方文档配置:

logger.add(
    logPath, 
    format="{time:YYYY-MM-DD at HH:mm:ss:SSS} | {message}",
    rotation=logger_rotation,
    retention=logRetention,
    compression=logCompression,
    encoding=logEncoding,
    enqueue=True,
)

这里为了是配置文件外置成config.ini,使用了configparser库,这样可以在不修改代码的情况下,通过修改配置文件来改变功能,这里不再赘述。

rotation函数

着重要说明的是rotation函数的配置,如果使用默认的rotation=00:00或者rotation=500 MB只能单一的实现每天或定量打包压缩日志,如果想要两种条件都匹配以及自定义一些条件,比如启动时打包便于本体开发人员截断之前日志等等,就需要使用自定义函数来实现,参考Log rotate by time and size #241:

class Rotator:

    def __init__(self, size, at):
        self._size = size
        now = datetime.now()
        today_at_time = now.replace(hour=at.hour, minute=at.minute, second=at.second)
        if now >= today_at_time:
            # the current time is already past the target time so it would rotate already
            # add one day to prevent an immediate rotation
            self._next_rotate = today_at_time + timedelta(days=1)
        else:
            self._next_rotate = today_at_time

    def should_rotate(self, message, file):
        file.seek(0, 2)
        if file.tell() + len(message) > self._size:
            return True
        if message.record["time"].timestamp() > self._next_rotate.timestamp():
            self._next_rotate += timedelta(days=1)
            return True
        return False

要实现每次启动程序,我的做法是定义一个全局变量和seek()值来判断是否需要return True,如果有更优美的实现请告诉我。这里也考虑过读取日志文件的创建时间来做判断,使用get_crtimes(os.path.abspath(file.name))在Linux系统下获得的时间为文件最后修改的时间,而不是文件创建的时间。

使用serial_asyncio

对于这种IO密集的逻辑和仅仅只是日志记录,最好的选择还是异步架构,Python的asyncio ,读取串口数据的https://pyserial-asyncio.readthedocs.io/en/latest/,程序伪代码如下:

async def handle_serial_data(reader, writer):
    while True:
        try:
            ByteData = await reader.readline()
            if ByteData and len(ByteData) > 3:  # filter of 3 strings data
                StrData = ByteData.decode(
                    "utf-8", errors='ignore')  # fix error
                StrData.strip().split("\n")
                logger.info(StrData)
            else:
                pass
        except Exception as e:
            # exception handle

async def main():
    try:
        loop = asyncio.get_event_loop()
        reader, writer = await serial_asyncio.open_serial_connection(
            loop=loop, url=serialPort, baudrate=serialBaudrate
        )

    except Exception:
        # exception handle
        return

    try:
        await handle_serial_data(reader, writer)
    finally:
        writer.close()
        await writer.wait_closed()

if __name__ == '__main__':
    try:
        asyncio.run(main())
    except Exception as e:
        logger.exception("main error!", type(e).__name__)

至此基本功能就实现了,结束了吗?

没~

因为忽视了程序实际运行的环境是树莓派而不是以往的服务器,而树莓派的eMMC寿命有限,所以日志内容分级处理和加入buffer,降低IO压力,以及使用Log2RAM,这里不谈。

在Ubuntu上使用Docker搭建ARM开发环境

由于日常开发的系统是Ubuntu 22.04,而树莓派则是ARM环境,一般来说,把Python当脚本跑的话没有区别的,但要是想用Pyinstaller打包的话,则要考虑运行环境了,为了后续开发需要,就使用Docker在Ubuntu上构建一个ARM环境。

docker buildx

docker buildx的Docker CLI插件,它允许你在不同的架构上构建Docker镜像。首先,安装并启用buildx插件:

# 安装docker buildx插件
docker buildx install

# 创建一个名为multiarch的构建实例,支持多种架构
docker buildx create --name multiarch

# 使用刚创建的multiarch实例
docker buildx use multiarch

安装QEMU模拟器:

sudo apt-get update && sudo apt-get install -y qemu-user-static

devcontainer.json

{
     "name": "ARM Python Development Environment",
     "dockerFile": "Dockerfile",
     "settings": {
       "terminal.integrated.shell.linux": "/bin/bash"
     },
     "extensions": [
       "ms-python.python"
     ],
     "remoteUser": "root"
   }

Dockerfile

   # 使用 ARM 架构的 Python 基础镜像
   FROM arm32v7/python:3.9-slim

   # 更新软件包列表并安装一些基本的工具
   RUN apt-get update && apt-get install -y --no-install-recommends \
       build-essential \
       curl \
       git \
       libssl-dev \
       zlib1g-dev \
       libbz2-dev \
       libreadline-dev \
       libsqlite3-dev \
       wget \
       llvm \
       libncursesw5-dev \
       xz-utils \
       tk-dev \
       libxml2-dev \
       libxmlsec1-dev \
       libffi-dev \
       liblzma-dev \
   && rm -rf /var/lib/apt/lists/*

   # 在此处添加其他 Docker 指令

构建完成后,查看系统环境:

dpkg --print-architecture