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

在Linux上使用DuckCP实现从csv文件汇总数据到SQLite数据库的表

从pypi网站Duckcp页面下载duckcp-0.1.1-py3-none-any.whl
一开始用的Python 3.11.2环境。
继续沿用上文打补丁的方法,得到一个支持python3.11.1的安装包。
因为缺少zip压缩工具,使用python程序来完成对修改后文件的重新压缩。

import os
import zipfile
from pathlib import Pathdef zip_directory_contents(source_dir, output_zip):"""压缩目录下的所有内容到ZIP文件(不包括根目录本身):param source_dir: 要压缩的目录路径:param output_zip: 输出的ZIP文件路径"""source_path = Path(source_dir).resolve()with zipfile.ZipFile(output_zip, 'w', zipfile.ZIP_DEFLATED) as zipf:for root, dirs, files in os.walk(source_dir):# 计算相对于源目录的路径rel_path = os.path.relpath(root, start=source_path)for file in files:file_path = Path(root) / file# 在ZIP中存储的相对路径(去掉最外层的a/)arcname = os.path.join(rel_path, file)zipf.write(file_path, arcname=arcname)# 确保空目录也被包含if not files and not dirs:# 添加空目录(必须以/结尾)rel_dir = os.path.relpath(root, start=source_path) + '/'zipf.writestr(rel_dir, '')zip_directory_contents('/par/whl/', '/par/whloutput_zip')

将得到的zip文件重命名为原始文件名,然后安装

mv /par/whloutput_zip /par/duckcp-0.1.1-py3-none-any.whlpython3 pip.pyz install  /par/duckcp-0.1.1-py3-none-any.whl --break-system-packages -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple

安装过程没有报错。
1.创建配置元数据库

duckcp meta create
Traceback (most recent call last):File "/usr/local/bin/duckcp", line 5, in <module>from duckcp import mainFile "/usr/local/lib/python3.11/dist-packages/duckcp/__init__.py", line 5, in <module>from duckcp.boot import app, meta_command, repository_command, storage_command, transformer_command, task_commandFile "/usr/local/lib/python3.11/dist-packages/duckcp/boot/__init__.py", line 5, in <module>from duckcp.configuration.meta_configuration import enable_metadata_configurationFile "/usr/local/lib/python3.11/dist-packages/duckcp/configuration/meta_configuration.py", line 9, in <module>from duckcp.entity.executor import ExecutorFile "/usr/local/lib/python3.11/dist-packages/duckcp/entity/executor.py", line 69def records[T: tuple[Any, ...]](self, sql: str, *parameters: Any, constructor: RecordConstructorProtocol[T] = None) -> list[T]:^
SyntaxError: expected '('

创建元数据库报错,应该就是不支持python3.11版本。改用Python 3.13.1,这一步顺利完成。需要说明,这些步骤都是由于我的环境和软件要求的Python版本不同引起的,如果版本正确, 这些问题都不会发生。

duckcp meta create2025-07-28 07:02:08.448 INFO duckcp.service.meta_service#meta_create : 配置文件(/root/.config/com.yinfn.duckcp/configuration.db)初始化                                      ]8;id=117526;file:///usr/local/lib/python3.13/site-packages/duckcp/service/meta_service.pymeta_service.py]8;;:]8;id=511219;file:///usr/local/lib/python3.13/site-packages/duckcp/service/meta_service.py#2020]8;;
2025-07-28 07:02:08.452 INFO duckcp.service.meta_service#meta_create : 执行脚本(001-repositories.sql)                                                                       ]8;id=289077;file:///usr/local/lib/python3.13/site-packages/duckcp/service/meta_service.pymeta_service.py]8;;:]8;id=303663;file:///usr/local/lib/python3.13/site-packages/duckcp/service/meta_service.py#2424]8;;

命令输出的信息有点多,向软件作者张泽鹏先生请教,他说可以用-q选项减少输出。但我们首次使用时,信息多更有利于排查问题。
2.创建源和目标存储库
因为我要实现从csv文件汇总数据,所以要在配置元数据库中登记csv文件存储位置。
通过以下命令完成

duckcp repository create 文件仓库 -k file --folder data

作为数据源的csv文件,直接复制自duckcp例子,因为复制出来的字符分隔符是tab字符,所以改名为progs.tsv

id	name	language
1	Joe	Java
2	Alice	JavaScript
3	Leon	C/C++
4	William	Java
5	James	C/C++
6	Enson	C/C++

对于目标,我一开始用的命令是,

duckcp repository create sqlite -k sqlite  --folder data --file sqlite.db

以为这样就能把data目录下的sqlite.db数据库作为目标,其实不然,打开配置元数据库检查,里面的内容如下。

./sqlite3 $HOME/.config/com.yinfn.duckcp/configuration.db
sqlite> .tables
credentials         snapshots           tasks               transformers      
repositories        storages            tasks_transformerssqlite> .header on
sqlite> select * from repositories;
id|kind|code|properties|created_at|updated_at
1|file|文件仓库|{"folder":"/par/data"}|2025-07-28 07:18:32|2025-07-28 07:18:32
2|sqlite|sqlite|{"file":"/par/sqlite.db","folder":"/par/data"}|2025-07-28 07:20:25|2025-07-28 07:20:25

sqlite所在行的properties列显示不符合预期。
张泽鹏先生说,数据库无需使用–folder参数,只要在–file中写明完整路径即可。所以正确命令如下:

duckcp repository create sqlite2 -k sqlite --file data/sqlite.db

因为duckcp本质上是一个ETL工具,它不会帮我们建库,所以要事先手工用sqlite软件实际创建data目录下的sqlite.db数据库,并建立保存目标数据的表。

./sqlite3 data/sqlite.db
sqlite> create table prog_sum(language varchar,cnt int);
sqlite> .exit

3.创建存储单元
存储单元这个名字的含义是数据库里的表的别名,我一开始漏掉了这一步,执行后面的命令就出错了main : 目标仓库(sqlite2)的存储单元(prog_sum)不存在

duckcp storage create prog_sum -r sqlite2 --table prog_sum

4.创建数据迁移任务
第一步是建立一个sql脚本,它负责读取源表(本例是Csv文件)执行汇总。
我直接照搬duckcp例子中的脚本,改了文件名。保存为data/trans.sql

select"language" as "编程语言",count(*) as "程序员人数"
fromread_csv('progs.tsv')
group by"language"
order by"程序员人数" desc

然后执行命令

duckcp transformer create 数据统计 -s 文件仓库 -t sqlite2 -o prog_sum -f data/trans.sql

5.执行数据迁移任务

duckcp transformer execute 数据统计
2025-07-28 08:28:36.086 INFO duckcp.transform.database_transform#database_transform : 清空表(DELETE FROM "prog_sum")                                                  ]8;id=758441;file:///usr/local/lib/python3.13/site-packages/duckcp/transform/database_transform.pydatabase_transform.py]8;;:]8;id=170976;file:///usr/local/lib/python3.13/site-packages/duckcp/transform/database_transform.py#3030]8;;
2025-07-28 08:28:36.221 INFO duckcp.transform.database_transform#database_transform : 批量添加数据(INSERT INTO "prog_sum" ("编程语言", "程序员人数") VALUES (?, ?))   ]8;id=941332;file:///usr/local/lib/python3.13/site-packages/duckcp/transform/database_transform.pydatabase_transform.py]8;;:]8;id=508716;file:///usr/local/lib/python3.13/site-packages/duckcp/transform/database_transform.py#3535]8;;
2025-07-28 08:28:36.224 ERROR duckcp#main : table prog_sum has no column named 编程语言  

又报错了,但这是最后一个错误,提示信息也很明确,只要把目标表的列名改成和上述sql一模一样的列名就行了。

./sqlite3 data/sqlite.db
sqlite> alter table prog_sum rename language to "编程语言";
sqlite> alter table prog_sum rename cnt to "程序员人数";
sqlite> .exit

再次执行任务,当看到transformer_execute : 从仓库(文件仓库)迁移数据到仓库(sqlite2)的存储单元(prog_sum) 信息就表明数据迁移成功,此时可以用sqlite打开目标表,结果符合预期。

sqlite> select * from prog_sum;
C/C++|3
Java|2
JavaScript|1

下面验证源文件更新后,数据重新汇总的结果被转移到目标表。

./duckdb131
DuckDB v1.3.1 (Ossivalis) 2063dda3e6
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.D select * from 'data/progs.tsv';
┌───────┬─────────┬────────────┐
│  id   │  name   │  language  │
│ int64 │ varcharvarchar   │
├───────┼─────────┼────────────┤
│     1 │ Joe     │ Java       │
│     2 │ Alice   │ JavaScript │
│     3 │ Leon    │ C/C++      │
│     4 │ William │ Java       │
│     5 │ James   │ C/C++      │
│     6 │ Enson   │ C/C++      │
└───────┴─────────┴────────────┘
D copy( from 'data/progs.tsv' union all select 7,'zhang3','sql') to 'data/progs.tsv'; 
D select * from 'data/progs.tsv';
┌───────┬─────────┬────────────┐
│  id   │  name   │  language  │
│ int64 │ varcharvarchar   │
├───────┼─────────┼────────────┤
│     1 │ Joe     │ Java       │
│     2 │ Alice   │ JavaScript │
│     3 │ Leon    │ C/C++      │
│     4 │ William │ Java       │
│     5 │ James   │ C/C++      │
│     6 │ Enson   │ C/C++      │
│     7 │ zhang3  │ sql        │
└───────┴─────────┴────────────┘
D .exit
root@217449ea9d61:/par# duckcp transformer execute 数据统计
2025-07-28 08:51:51.005 INFO duckcp.transform.database_transform#database_transform : 清空表(DELETE FROM "prog_sum")                                                  ]8;id=353910;file:///usr/local/lib/python3.13/site-packages/duckcp/transform/database_transform.pydatabase_transform.py]8;;:]8;id=259843;file:///usr/local/lib/python3.13/site-packages/duckcp/transform/database_transform.py#3030]8;;
2025-07-28 08:51:51.123 INFO duckcp.transform.database_transform#database_transform : 批量添加数据(INSERT INTO "prog_sum" ("编程语言", "程序员人数") VALUES (?, ?))   ]8;id=595510;file:///usr/local/lib/python3.13/site-packages/duckcp/transform/database_transform.pydatabase_transform.py]8;;:]8;id=232644;file:///usr/local/lib/python3.13/site-packages/duckcp/transform/database_transform.py#3535]8;;
2025-07-28 08:51:51.323 INFO duckcp.service.transformer_service#transformer_execute : 从仓库(文件仓库)迁移数据到仓库(sqlite2)的存储单元(prog_sum)                   ]8;id=489086;file:///usr/local/lib/python3.13/site-packages/duckcp/service/transformer_service.pytransformer_service.py]8;;:]8;id=370598;file:///usr/local/lib/python3.13/site-packages/duckcp/service/transformer_service.py#273273]8;;
root@217449ea9d61:/par# ./sqlite3 data/sqlite.db
SQLite version 3.42.0 2023-05-16 12:36:15
Enter ".help" for usage hints.
sqlite> .header on
sqlite> select * from prog_sum;
编程语言|程序员人数
C/C++|3
Java|2
sql|1
JavaScript|1

可见,结果多出了sql|1这行,它就是数据源插入zhang3的结果。

http://www.dtcms.com/a/303596.html

相关文章:

  • 数据开源 | “白虎”数据集首批开源,迈出百万数据征途第一步
  • Zynq SOC FPGA嵌入式裸机设计和开发教程自学笔记:硬件编程原理、基于SDK库函数编程、软件固化
  • 2.DRF 序列化器-Serializer
  • 第五章:进入Redis的Hash核心
  • 小架构step系列28:自定义校验注解
  • 【算法训练营Day17】二叉树part7
  • 【VASP】二维材料杨氏模量与泊松比的公式
  • OpenLayers 综合案例-信息窗体-弹窗
  • 打卡day5
  • C++面试5题--5day
  • C++中的“对象切片“:一场被截断的继承之痛
  • 【SpringMVC】MVC中Controller的配置 、RestFul的使用、页面重定向和转发
  • rhel9.1配置本地源并设置开机自动挂载(适用于物理光驱的场景)
  • c++ 基础
  • windows内核研究(异常-CPU异常记录)
  • 嵌入式分享合集186
  • STM32时钟源
  • JavaScript手录09-内置对象【String对象】
  • 第一章:Go语言基础入门之函数
  • wrk 压力测试工具使用教程
  • 屏幕晃动机cad【4张】三维图+设计说明书
  • 多信号实采数据加噪版本
  • 详解 Electron 应用增量升级
  • 轻量级远程开发利器:Code Server与cpolar协同实现安全云端编码
  • 2. 编程语言-JAVA-Spring Security
  • 记录自己第n次面试(n>3)
  • JavaScript手录08-对象
  • 深入解析IPMI FRU规范:分区结构与字段标识详解
  • 10_opencv_分离颜色通道、多通道图像混合
  • Nuxt3 全栈作品【通用信息管理系统】修改密码