当前位置: 首页 > article >正文

ChatGPT 并非总是理解 SQL,但这个 Python 工具可以

原文towardsdatascience.com/say-goodbye-to-sql-headaches-with-this-python-tool-75099f5ff33dhttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f411ec0f210c2545786c1022c49304d5.pngImage by 2023852 from Pixabay如果你是一位每天与数据打交道的开发者或分析师SQL 查询对于许多不同的角色来说将是必不可少的技能之一。当我还在大学里当导师的时候有一个学生抱怨 SQL 是世界上最糟糕的编程语言。好吧SQL 是否是“编程语言”可能存在争议。然而毫无疑问它在语法方面相当结构化和严格。因此实现这样一个工具来完全理解其含义将会相对容易。不我们不需要 ChatGPT。在这篇文章中我将介绍一个帮助我们解析 SQL 查询甚至可以编程构建查询的库。如果你不知道为什么我们需要这样做那么阅读剩余内容将更加重要。1. 安装https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/976f3767eed4a1ccf77e6092e3c2291e.pngImage by AndreasAux from Pixabay像往常一样这部分内容可能有些枯燥但无论如何我必须包含这一部分。要安装这个库只需简单地运行以下命令。pip install sqlglot此外如果你处于一个更加灵活的环境比如你的笔记本电脑建议安装该软件包及其 Rust 分词器。这将使解析过程更加高效。pip3 installsqlglot[rs]然后在我们的 Python 代码中在使用之前我们应该导入这个库。在本文的所有示例中我将使用别名sg来代表库sqlglot因为我们在这个包中需要使用多个不同的函数。如果你想运行我的示例请别忘了运行下面的代码行。importsqlglotassg2. 之间不同 SQL 方言的转换https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/0be18d27fb7f56006514273268b6dc40.pngImage by Joe from Pixabay这是今天这个库将提供的第一个用例。我会给你一个我在工作中的真实用例。这发生在两年前。我们有一个遗留的数据可视化工具它连接到我们的 Azure Synapse然后运行大量的 SQL 查询以获取渲染到图表中的结果。我们的一个项目是退役 Azure Synapse 并拥抱 Databricks。然而问题是在那个可视化工具中有超过 500 个仪表板和数千个 SQL 查询需要从 T-SQL 转换为 Databricks SQL 以实现兼容性。我们为此付出了很多努力。当时不幸的是我们并不知道这个sqlglot库。现在让我们举一个简单的例子。假设我们有一个以下的 Databricks SQL 查询。大多数语法应该是通用的但LIMIT 10是针对某些数据库管理系统的特定用法。databricks_querySELECT * FROM Customer LIMIT 10如果你熟悉 SQL Server 或 Azure Synapse它们使用不同的语法来限制结果集的行数。那就是SELECT TOP n ... FROM ...。现在让我们看看如何使用sqlglot非常容易地反编译查询。sg.transpile(databricks_query,readdatabricks,writetsql)[0]在上面的代码中我们调用了sqlglot中的transpile()函数。然后我们提供了 SQL 语句databricks_query。然后我们告诉该函数这是一个 Databricks 方言readdatabricks并且我们希望它将其反编译为 T-SQLwritetsql。值得注意的是该函数实际上会返回一个列表。这是以防查询字符串中包含多个 SQL 语句的情况如下所示。SELECT*FROM Customer LIMIT10;SELECT*FROM Product LIMIT10;好的回到我们的反编译。我们只需要按照以下方式打印反编译后的 SQL 查询。print(sg.transpile(databricks_query,readdatabricks,writetsql)[0])我们可以看到查询已经正确地反编译为 T-SQL。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/19a6f4ed7a12208e203aff3480d4343d.png当然我们也可以将其从 T-SQL 反编译回 Databricks SQL如下所示。tsql_querySELECT TOP 10 * FROM Customerprint(sg.transpile(tsql_query,readtsql,writedatabricks)[0])https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1d29f2968a5fb63a33f9f0b48c21e0b5.png另一个需要提到的是sqlglot在反编译时会尽力保留原始查询中的所有元素。例如如果查询中有一个注释它将保留它。tsql_query -- Get 10 Customers SELECT TOP 10 * FROM Customer print(sg.transpile(tsql_query,readtsql,writedatabricks)[0])上述代码给出了以下输出。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/664ec7f5df7273e0440dd45719d35190.png3. 美观格式化https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/646c53d32f3c4156915139da09f0c665.pngImage by Radosław Cieśla from Pixabay毫不奇怪的是sqlglot可以格式化 SQL 查询并以美观的格式输出因为它毕竟可以理解它。只需继续前面的例子尽管它输出带有注释的反编译查询但所有内容都在一行中。现在如果我们想提高可读性我们只需简单地将prettyTrue添加到函数中。print(sg.transpile(tsql_query,readtsql,writedatabricks,prettyTrue)[0])https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/868d77a8a6e717b5b95007f365a46ef0.png看看注释不仅有一个新行查询本身也被格式化为美观样式。当然我们可以有一个更复杂的 SQL 查询如下所示。它也可以被格式化。sql WITH baz AS (SELECT a, c FROM foo WHERE a 1) SELECT f.a, b.b, baz.c, CAST(b.a AS REAL) d FROM foo f JOIN bar b ON f.a b.a LEFT JOIN baz ON f.a baz.a print(sg.transpile(sql,writedatabricks,identifyTrue,prettyTrue)[0])上述函数identityTrue表示目标方言未指定源方言也将用作目标方言。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/0b148007b6aee094d90a400de201a948.png4. 获取查询的元数据https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/929c183093e9c6064d44f18cfe36ac71.png图片由LUM3N在Pixabay提供这里还有一个来自我工作的实际用例。在我们的数据平台上每天都有数百个用户向我们的数据库发送即兴查询。我们有一个强烈的需求那就是我们想知道“在某个特定时间谁查询了哪个表”。这个信息非常有用。例如一旦我们想要更改任何表我们就知道可能会受到影响的人。此外一些一年多没有使用过的表可能是一个减少或移除数据摄入频率的潜在机会以节省我们的云成本。不幸的是Azure Synapse 的日志并没有提供这样的信息从 SQL 查询中提取表也不是一件容易的事情。由于当时我们并不知道sqlglot所以我们编写了一个完整的正则表达式分支来实现这个功能。假设我们有一个如下所示的查询。它有点复杂因为它包含了一个 CTE公共表表达式。如果sqlglot可以处理这个查询那么它也能处理任何类型的子查询。# SQL querysql with cte1 as ( SELECT a.col1, a.col2, b.col3, b.col4, c.col5 FROM Table_A a LEFT JOIN Table_B b ON a.id b.id ) SELECT * FROM cte1 LEFT JOIN Table_C c on cte1.col1 c.col1 # Function to extract table namesparsedsg.parse_one(sql)让我来举例说明为什么我们使用parse_one()函数。在sqlglot中还有一个名为parse()的函数。与上面的transpile()函数类似它能够解析一个查询中的多个语句并返回一个数组。在我们的上下文中我不想让例子过于复杂。所以让我们只使用一个语句parse_one()函数给我们一个解析树这更容易展示。在将 SQL 查询解析到变量parsed之后我们可以看看里面有什么。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/82b9ac91b76eb6c1ccfd2d7940362358.pngsqlglot有其术语来标记以树形层次结构对象的形式表示的查询。使用sqlglot不需要理解这个术语。所以不用担心我会向你展示。现在让我们从解析对象中获取所有表。fortable_expinparsed.find_all(sg.exp.Table):print(table_exp)https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/d4f232d48f2309a41bc9a00047f5887d.png在上面的代码中我们只是调用了find_all()函数到解析对象上它返回了我们正在寻找的一切的列表。sg.exp.Table是一个枚举它只是告诉函数我们特别在寻找表。同样还有sg.exp.Column、sg.exp.Schema等等。好吧上面输出中仍然有两个问题。让我们假设我们只关心表名称而不是表别名和 CTE 名称。虽然这次可能不会完全现成但仍然不难且相当直观地实现。简单的想法是我们想要获取所有的 CTE 名称然后获取所有的表名称无论在表名称集中还是在 CTE 名称集中但不在表名称集中的都是感兴趣的。首先让我们找到所有的 CTE 名称。ctesset()forcteinparsed.find_all(sg.exp.CTE):ctes.add(cte.alias)枚举项sg.exp.CTE告诉find_all()函数获取所有 CTE。然后我们将cte.alias添加到ctes集中。然后让我们获取一个集中的所有表。我们可以通过调用table_exp.text(this)来获取标识符从而得到只包含名称的字符串。在我们将每个表名称添加到集中之前只需检查它是否在 CTE 集中。如果是则不要添加。tablesset()fortable_expinparsed.find_all(sg.exp.Table):table_nametable_exp.text(this)iftable_namenotinctes:tables.add(table_name)让我们执行代码并获取查询中的表名称集。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/33866a419db5b5b28b5d6edaa662c949.png5. 错误处理https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f516a4e003befcf2e69d8b4460cecdef.pngErich Westendarp从Pixabay提供的图片到目前为止你可能想知道如果 SQL 语言无效会怎样。不用担心sqlglot会捕获它并告诉你错误在哪里以及为什么它不是一个有效的 SQL 查询。假设我们有一个以下查询。SELECT foo(FROM bar我们可以快速判断它不是一个有效的 SQL。让我们尝试解析它并捕获错误。错误是sqlglot提供的sg.errors.ParseError。importpprinttry:sg.parse(SELECT foo( FROM bar)exceptsg.errors.ParseErrorase:pprint.pprint(e.errors)在这个例子中我想仅为了演示目的利用pprint。它将以美观的格式输出错误信息。否则列表将一行打印出来。不用担心你的情况。你不必使用pprint。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/9b1b2638e6866f148536fe16ad8998d4.png我们可以看到错误信息中包含了足够关于位置和错误类型的信息。6. 以编程方式构建 SQL 语句https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4e61ef07955b91f2d66ac11b0ae40ca3.pngeko pramono从Pixabay提供的图片为什么我们想要使用sqlglot为我们构建 SQL 语句根据你的实际场景可能有多个潜在的原因。减少 SQL 注入攻击的风险错误处理和验证可读性可维护性可扩展性我在这里只举一个例子。在代码中看到人们使用WHERE 11是很常见的。确实当处理我们不确定是否会有过滤条件的情况时这是一个聪明的解决方案。然而这是一个很好的例子证明了使用字符串构造技术构建 SQL 语句是有局限性的。也就是说我们需要处理语法不允许将一致的模式附加到查询字符串中的情况。现在让我们构建一个简单的查询来尝试sqlglot的这个功能。querysg.select(*).from_(Customer).where(sg.condition(age 18).and_(is_vip Y))print(query.sql())带下划线的from_()和and_()函数只是为了避免与 Python 的原生函数命名冲突所以请不要感到困惑这里并没有什么魔法与下划线有关。可以使用.sql()将构建的查询转换为字符串。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/53e2ae68602872796614f7bb36bd3739.png这个功能的另一个用例可能是多语言需求。也就是说一旦我们构建了查询我们就可以轻松地将其输出到不同的 SQL 语法中。让我们使用开始时提到的相同示例构建以下查询。# Building the queryquerysg.select(*).from_(Customer).limit(10)现在我们可以将查询输出到 Databricks SQL 中。# Generate query for Databricks SQL dialectsql_databricksquery.sql(dialectdatabricks)print(sql_databricks)https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3c445bd9f0d93d2cf2012c533e8316df.png当然我们也可以轻松地以 T-SQL 语法输出它无需重新构建或转译。# Generate query for T-SQL dialectsql_tsqlquery.sql(dialecttsql)print(sql_tsql)https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/bb86ba84965e1f5aa403d3b771ffa7a6.png7. 查询优化https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1987810fd4268e0fc29720a4d0441166.png图片由 Andrew Martin 提供来自 Pixabay最后但同样重要的是这个库也具有某种查询优化能力。例如如果我们定义了如下非常复杂的条件。bad_sqlsg.parse_one( SELECT * FROM my_table WHERE a1 OR (b2 OR (c3 AND d4)) )我可以说它甚至都不好读。现在让我们看看sqlglot如何优化它。good_sqlsg.optimizer.optimize(bad_sql)print(good_sql.sql(prettyTrue))https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/96231feebf270e477de840e98ad4f063.png它仍然很复杂但现在读起来要容易得多。除了优化语法表达式外它还可以实现常见的查询优化以提高性能。然而可能需要提供大量的上下文。如果您对此感兴趣可以亲自尝试一下。摘要https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/776edaca74a6778b933e8f49897e0033.png图片由 Mircea Ploscar 提供来自 Pixabay到目前为止我们已经看到了sqlglot提供的许多功能。我相信其中之一或多个应该有机会提高我们的生产力甚至解决我们从未能够解决的问题。这个库在生成式 AI 时代向我们展示了某种确定性是一块宝石。是的我是在说 ChatGPT 有时可能会给我们错误。然而对于像 SQL 这样的语法更加严格的编程语言我们当然不必验证sqlglot生成的 SQL 查询。肯定地说它无论如何都会正常工作 除非另有说明所有图片均由作者提供

相关文章:

ChatGPT 并非总是理解 SQL,但这个 Python 工具可以

原文:towardsdatascience.com/say-goodbye-to-sql-headaches-with-this-python-tool-75099f5ff33d https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f411ec0f210c2545786c1022c49304d5.png Image by 2023852 from Pixabay 如果…...

seo代做如何评估投资回报率

SEO代做如何评估投资回报率:实用指南与解决方案 在现代数字营销中,SEO(搜索引擎优化)代做服务成为了许多企业提升网站流量和销售的重要手段。如何评估SEO代做的投资回报率(ROI)是许多企业面临的关键问题。…...

FUSB302 Arduino库:USB-C物理层与PD协议硬件协同开发指南

1. 项目概述Sitron Labs FUSB302 Arduino Library 是一款面向嵌入式开发者的专业级 USB Type-C 控制器驱动库,专为 onsemi(原安森美)FUSB302 系列可编程 USB Type-C 端口控制器设计。该库并非简单封装 I2C 读写操作,而是完整实现了…...

SEO_本地SEO优化的关键步骤与操作技巧

SEO:本地SEO优化的关键步骤与操作技巧 在当今数字化时代,本地SEO优化已经成为企业提升在线存在感和吸引本地客户的重要手段。无论你是小型本地企业,还是大型品牌,本地SEO优化都能帮助你更好地连接到潜在客户。具体该如何进行本地SEO优化呢&a…...

如何结合本地SEO优化来免费提高网站排名

如何结合本地SEO优化来免费提高网站排名 在当前数字化时代,网站排名的提升已经成为了企业和个人网站的重要目标之一。而对于本地企业来说,如何通过本地SEO优化来提高网站排名,是一个非常关键的问题。本文将详细探讨如何结合本地SEO优化来免费…...

不用精确模型也能控?手把手教你用Matlab实现MFAC控制算法(附完整代码)

零基础实现MFAC控制:Matlab实战指南与参数调优全解析 在控制工程实践中,我们常常遇到这样的困境:面对一个复杂的非线性系统(比如实验室里的倒立摆或者工厂中的液位控制装置),传统的PID控制效果不佳&#xf…...

CVPR 2023 TKSA注意力机制实战:手把手教你用PyTorch实现Top-K稀疏注意力模块

CVPR 2023 TKSA注意力机制实战:手把手教你用PyTorch实现Top-K稀疏注意力模块 在计算机视觉领域,注意力机制已经成为提升模型性能的关键组件。然而,传统注意力机制的计算开销和内存消耗常常成为制约模型效率的瓶颈。CVPR 2023提出的Top-K稀疏注…...

学生-教师模型避坑指南:EfficientAD在MVTec数据集上的调参心得

EfficientAD实战避坑手册:MVTec数据集调参策略与异常检测优化 工业质检场景对视觉异常检测的实时性要求近乎苛刻——产线上每秒流过数百个零件时,2毫秒的延迟差异就可能造成数百万损失。这正是EfficientAD吸引开发者的核心价值:在保持SOTA精度…...

PyTorch与torchvision版本兼容性全解析:从安装到升级的避坑指南

1. PyTorch与torchvision版本兼容性基础 刚接触深度学习框架时,我最先踩的坑就是PyTorch和torchvision版本不匹配。明明按照教程安装了最新版,运行时却报出各种奇怪的错误,后来才发现是这两个库的版本没对齐。这就像买手机时充电器和数据线必…...

OpenClaw配置备份指南:千问3.5-27B模型参数迁移技巧

OpenClaw配置备份指南:千问3.5-27B模型参数迁移技巧 1. 为什么需要备份OpenClaw配置? 上周我的主力开发机突然硬盘故障,不得不紧急更换设备。当我准备在新电脑上重新部署OpenClaw时,突然意识到一个严重问题:过去三个…...

别再只跑官方Demo了!用UA-DETRAC数据集手把手教你训练一个能分清‘轿车、巴士、货车’的YOLOv5s车辆检测模型

从UA-DETRAC到精准车辆分类:YOLOv5s实战进阶指南 当交通监控摄像头捕捉到一辆快速驶过的车辆时,系统需要在一瞬间判断这是需要重点追踪的嫌疑车辆,还是普通通勤轿车。这种毫秒级的决策背后,是目标检测模型对车辆类型精准识别的能力…...

从‘汉宁窗’到‘凯泽窗’:手把手教你用Python SciPy为你的音频降噪项目挑选最合适的FIR窗函数

从‘汉宁窗’到‘凯泽窗’:Python SciPy窗函数在音频降噪中的实战选择指南 当一段珍贵的录音被50Hz工频噪声污染时,我们面临的不仅是技术问题,更是艺术与科学的平衡。窗函数作为FIR滤波器设计中的关键参数,直接影响着滤波器在频率…...

CH582F + W100DP打造微型气象站:从数据采集到蓝牙上传的完整项目

CH582F W100DP微型气象站开发实战:从硬件搭建到数据可视化 1. 项目规划与硬件选型 在物联网设备开发中,选择合适的硬件平台和传感器往往决定了项目的成败。我们选择了沁微CH582F作为主控芯片,搭配维安W100DP数字气压传感器,构建一…...

北京SEO优化对网站有哪些影响

北京SEO优化对网站有哪些影响 在当今数字化时代,网站的SEO优化已经成为企业提升在线曝光和吸引潜在客户的重要手段。尤其在北京这个国际大都市,优化SEO不仅能够提升网站在本地的排名,还能带来更多的本地客户。本文将详细探讨北京SEO优化对网…...

OpenClaw语音交互:Qwen3.5-9B实现钉钉语音指令转任务执行

OpenClaw语音交互:Qwen3.5-9B实现钉钉语音指令转任务执行 1. 为什么需要语音交互的自动化助手 作为一个长期被会议纪要和日报折磨的开发者,我一直在寻找能解放双手的解决方案。键盘快捷键和脚本自动化虽然能解决部分问题,但当我在通勤路上突…...

HC-SR04测距不准?STM32定时器输入捕获模式详解与精度提升技巧

HC-SR04测距不准?STM32定时器输入捕获模式详解与精度提升技巧 超声波测距模块HC-SR04因其低成本、易用性在嵌入式领域广泛应用,但许多开发者发现实际测量结果常出现波动大、数据不准的问题。本文将深入分析误差来源,并基于STM32定时器的输入捕…...

鸿蒙音频开发避坑指南:用AVPlayer实现音乐App的熄屏播放,这3个权限和配置项别忘了

鸿蒙音频开发实战:熄屏播放的三大核心配置与避坑策略 在移动应用生态中,音频播放功能始终占据重要地位——无论是音乐流媒体、播客平台还是语音社交应用,流畅的后台播放体验都是用户留存的关键指标。鸿蒙系统通过AVPlayer与Media Kit为开发者…...

压缩感知基础:从稀疏信号到高效重构

1. 压缩感知是什么? 第一次听说"压缩感知"这个词时,我完全摸不着头脑。直到在研究生阶段接触到医学影像处理,才发现这个理论简直是个宝藏。简单来说,压缩感知(Compressed Sensing, CS)是一种颠覆…...

基于PLECS和MATLAB Simulink的250V直流输入至1000V输出单相九电平级联...

单相九电平级联NPC逆变器模块,输入250V直流,输出交流幅值1000V,电阻负载。 PLECS平台搭建,MATLAB/simulink也可实现。手把手玩转九电平NPC逆变器仿真最近在实验室折腾单相九电平级联NPC逆变器,输入250V直流硬是怼出100…...

从二层到三层:华为交换机vlanif接口的进阶用法与避坑指南

从二层到三层:华为交换机vlanif接口的进阶用法与避坑指南 在网络设备管理中,华为交换机的vlanif接口(也称为SVI,Switch Virtual Interface)是连接二层与三层功能的关键桥梁。对于已经掌握基础配置的网络管理员而言&…...

OpenClaw技能扩展实战:用Qwen3.5-9B自动生成技术博客并发布

OpenClaw技能扩展实战:用Qwen3.5-9B自动生成技术博客并发布 1. 为什么选择OpenClawQwen3.5-9B组合 去年我开始尝试用AI辅助技术写作时,最头疼的就是内容生产链路的断裂——用大模型生成草稿后,还需要手动复制到编辑器、调整格式、添加Front…...

SparkFun HyperDisplay SSD1309 OLED驱动库详解

1. 项目概述SparkFun HyperDisplay SSD1309 是 SparkFun Electronics 针对基于 SSD1309 显示驱动芯片的 OLED 模块推出的标准化嵌入式显示控制库。该库并非独立实现,而是作为 SparkFun HyperDisplay 显示抽象框架(Display Abstraction Framework&#xf…...

OpenClaw+Qwen3-14b_int4_awq:自动化数据整理工具

OpenClawQwen3-14b_int4_awq:自动化数据整理工具 1. 为什么需要自动化数据整理 作为一名经常和数据打交道的研究人员,我每天都要面对各种格式混乱的Excel表格、CSV文件和PDF报告。最让我头疼的是,每次收集到新数据,都要手动清洗…...

2026届毕业生推荐的十大AI学术平台解析与推荐

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 对内容创作领域而言,降低AI生成文本的检测比率成了重要课题。其一,建…...

OpenClaw+Qwen3-32B-Chat镜像:自媒体内容生产全流程自动化

OpenClawQwen3-32B-Chat镜像:自媒体内容生产全流程自动化 1. 为什么需要自动化内容生产? 作为一个自媒体创作者,我每天要花大量时间在重复性工作上:追踪热点、构思选题、撰写大纲、生成初稿、设计封面、多平台发布...这些工作占…...

从仿真到版图:在ADS里完成Wilkinson功分器设计后,别忘了检查这几个Layout细节

从仿真到版图:Wilkinson功分器设计中的关键Layout细节解析 在微波电路设计中,Wilkinson功分器作为经典的功率分配/合成器件,其性能优劣直接影响整个射频系统的表现。许多工程师在ADS中完成仿真优化后,往往对自动生成的版图过于信任…...

GB2312编码逆向剖析:用Logisim拆解LED屏汉字显示背后的区位码秘密

GB2312编码逆向工程:从LED屏汉字显示到区位码转换全链路解析 当你在街头看到LED显示屏滚动播放汉字时,是否思考过这些光点背后隐藏着怎样的编码奥秘?作为中文信息处理的基石,GB2312标准通过区位码、国标码、机内码的三重转换机制&…...

LoRaWAN Arduino库:Grove Wio E5轻量级接入方案

1. 项目概述LoRaWAN-Seeed-Grove-Wio-E5 是一个面向嵌入式开发者的轻量级 Arduino 库,专为 Grove Wio E5 LoRa-E5 模块设计。该模块基于 Semtech SX1276 射频芯片,集成 ARM Cortex-M0 内核(nRF52832),出厂预烧录 AT 固…...

.NET 高级开发 | 配置系统

配置和选项ASP.NET Core 模板项目下会有 appsettings.json、appsettings.Development.json 两个配置文件,我们可以通过这两个文件配置 Web 应用的启动端口、是否使用 https 等,大多数第三方框架也都支持在这两个 json 文件中配置。ASP.NET Core 程序默认…...

最开放的Gemma 4来了——谷歌:没人比我更懂“不作恶”。

2026 年 4 月 2 日,谷歌 DeepMind 发布了 Gemma 4 系列模型[1]。模型有四个规格——E2B、E4B、26B MoE、31B Dense——覆盖了从树莓派到单卡 H100 的全硬件区间,31B 在 Arena 开源榜冲到第三,26B MoE 只激活 38 亿参数就打出了同级 Dense 模型…...