Python动态处理海量Kafka数据:字典替代动态变量名的实战方案

栗子
栗子
发布时间:2026-10-13| 6人浏览过
原创

本文针对每日千万级Kafka数据写入磁盘的场景,探讨了如何高效管理动态生成的文件及计数器。通过对比尝试使用exec等动态语法失败的经历,最终提出利用三个独立字典分别存储计数器、时间戳和分类信息的解决方案。该方法避免了定义海量变量的性能损耗,实现了基于配置条数自动切换文件后缀(tmp转out)的稳定处理流程。

在将Kafka数据消费并持久化到磁盘的过程中,曾遇到如下挑战:

具体需求为:日均处理约1千万条数据,每条记录包含19个字段。需将数据写入服务器磁盘,依据第二个字段作为大类创建目录,第七个字段结合时间戳作为文件名,临时文件后缀设为tmp。当单个文件写入条数达到可配置阈值(例如100条)时,将后缀由tmp更新为out。

核心难点在于:大类共30种,小类数量庞大且不可预知。例如,若大类为A,小类为a,时间戳为20180606095835234,则A目录下生成的文件名为20180606095835234_a.tmp。每当该文件写满100条时,需生成新的时间戳并创建第二个文件名。若同时存在1000个文件在写入,则需维护1000个时间戳和1000个计数器。若为每个文件单独定义变量,显然效率极低且不可行。

在解决思路的探索阶段,曾考虑动态定义变量名的方案,即:

提取第七个字段:seven = data.split('|')[7]

构建文件名:filename = time_stamp + '_' + seven+'.tmp'

初始化文件计数器:seven + ‘_num' = 0

初始化文件时间戳:seven + '_stamp' = time.time( )

该思路在逻辑上并无偏差,但关键在于如何用一个变量名与字符串拼接生成新变量名并赋值(表述可能不够精准)。尝试使用local()、global()及exec()函数均未达到预期效果,或许是将问题复杂化了。

最终,通过引入三个字典完美解决了该问题:

创建一个字典用于存储计数器,其键对应文件名,值对应当前写入条数,并实时更新;

创建另一个字典用于存储时间戳,键对应文件名,值对应时间戳,当计数达到100条时更新一次;

再创建一个字典用于存储大类映射,键对应代码,值对应分类名称;

局部功能实现代码如下:

def kafka_to_disk():
 print('启动前检测上次运行时是否存在意外中断的数据文件......')
 print('搜索最近一次执行脚本产生的时间目录......')
 # 待处理临时文件列表
 tmp_list = []
 try:
  for category_dir in os.listdir(local_file_path):
   if len(os.listdir(local_file_path+os.sep+category_dir)) > 0:
    for file in os.listdir(local_file_path+os.sep+category_dir):
     if suffix in file:
      tmp_list.append(local_file_path+os.sep+category_dir+os.sep+file)
  # print('上次运行程序产生的临时文件有---{}'.format(tmp_list))
 except Exception as e:
  pass
 if len(tmp_list) == 0:
  print('未扫描任何残留临时文件')
 else:
  print('开始修复残留临时文件......')
 tmp_num = 0
 for tmp in tmp_list:
  os.rename(tmp, tmp.split('.')[0]+'.out')
  tmp_num += 1
 print('本次启动共修复残留临时文件★★★★★-----{}个-----★★★★★'.format(tmp_num))
 
 category_poor = {
  '1': 'news', '2': 'weibo', '3': 'weixin', '4': 'app', '5': 'newspaper', '6': 'luntan',
  '7': 'blog', '8': 'video', '9': 'shangji', '10': 'shangjia', '11': 'gtzy', '12': 'zfztb',
  '13': 'gyfp', '14': 'gjz', '15': 'zfxx', '16': 'ptztb', '17': 'company', '18': 'house',
  '19': 'hospital', '20': 'bank', '21': 'zone', '22': 'express', '23': 'zpgw', '24': 'zscq',
  '25': 'hotel', '26': 'cpws', '27': 'gxqy', '28': 'gpjj', '29': 'dtyy', '30': 'bdbk'}
 
 time_stamp = utils.get_time_stamp() # 初始化毫秒级时间戳 : 20180509103015125
 consumer = KafkaConsumer(topic, group_id=group_id, auto_offset_reset=auto_offset_reset, bootstrap_servers=eval(bootstrap_servers))
 print('连接kafka成功,数据筛选中......')
 file_poor = {}       # 子类池用于文件计数器
 time_stamp_poor = {}     # 子类时间戳池,用于触发文件切换
 time_stamp = utils.get_time_stamp()  # 初始化毫秒级时间戳 :20180509103015125
 for message in consumer:
  # 提取第8个字段自动匹配目录进行创建
  if message.value.decode().split('|')[1] in category_poor:
   category = category_poor[message.value.decode().split('|')[1]]
  else:
   print(message.value.decode())
   continue
  category_dir = local_file_path + os.sep + category
  if not os.path.exists(category_dir):
   os.makedirs(category_dir)
  # 提取第2个字段,用于生成文件名
  if message.value.decode().split('|')[7] in time_stamp_poor:
   shot_file_name = time_stamp_poor[message.value.decode().split('|')[7]] + '_' + message.value.decode().split('|')[7]
  else:
   shot_file_name = time_stamp + '_' + message.value.decode().split('|')[7]
  file_name = category_dir + os.sep + shot_file_name + '.tmp'
 
  # 给每一个文件设定一个计数器
  if message.value.decode().split('|')[7] not in file_poor:
   file_poor[message.value.decode().split('|')[7]] = 0
 
  with open(file_name, 'a', encoding='utf-8')as f1:
   f1.write(message.value.decode())
   file_poor[message.value.decode().split('|')[7]] += 1
 
  # 触发切换文件的操作,用时间戳生成第二文件名
  if file_poor[message.value.decode().split('|')[7]] == strip_number:
   time_stamp_poor[message.value.decode().split('|')[7]] = utils.get_time_stamp()
   file_poor[message.value.decode().split('|')[7]] = 0

以上关于Python解决动态定义变量名及赋值的方案(应用于大数据处理)即为分享的全部内容,希望能为读者提供参考,并欢迎大家继续支持本站。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。