如何将Azure Blob存储的DataFrame传入read_block函数?
Azure Blob Storage数据与正则提取流程整合问题
问题背景
已分别验证从Azure Blob Storage获取数据、使用正则提取数据的代码功能正常,但无法将两段代码整合:需要用第一部分生成的DataFrame替换第二部分中本地文件Test.csv的输入,或直接使用Azure的下载对象。
第一部分:从Azure Blob Storage获取DataFrame的代码
import re from io import StringIO import pandas as pd from azure.storage.blob import BlobClient blob = BlobClient(account_url="https://test.blob.core.windows.net", container_name="xxxx", blob_name="Text.csv", credential="xxxx") data = blob.download_blob() df = pd.read_csv(data)
第二部分:原本地文件正则提取代码
def read_block(names, igidx=True): with open("Test.csv") as f: ###<<<需要修改的位置<<<### pat = r"(\w+),+$\n[^,]+.+?\n,+\n(.+?)(?=\n,{2,})" return pd.concat([ pd.read_csv(StringIO(m.group(2)), skipinitialspace=True) .iloc[:, 1:].dropna(how="all") for m in re.finditer( pat, f.read(), flags=re.M|re.S) if m.group(1) in names # optional ], keys=names, ignore_index=igidx) df2 = read_block(names=["Admissions", "Readmissions"],igidx=False).droplevel(1).reset_index(names="Admission")
尝试修改后的代码及错误记录
第一次修改及错误
尝试将DataFrame转为字符串传入正则匹配,出现ValueError: No objects to concatenate:
... data = blob.download_blob() df = pd.read_csv(data) df1 = df.to_csv(index=False, header=False) def read_block(names, igidx=True): pat = r"(\w+),+$\n[^,]+.+?\n,+\n(.+?)(?=\n,{2,})" return pd.concat([ pd.read_csv(StringIO(m.group(2)), skipinitialspace=True) .iloc[:, 1:].dropna(how="all") for m in re.finditer( pat, df1, flags=re.M|re.S) if m.group(1) in names ], keys=names, ignore_index=igidx) df2 = read_block(names=["Admissions", "Readmissions"], igidx=False).droplevel(1).reset_index(names="Admission") print(df2)
错误信息:
ValueError: No objects to concatenate
第二次修改及错误
尝试直接使用data.readall(),出现编码错误:
import re from io import StringIO import pandas as pd from azure.storage.blob import BlobClient blob = BlobClient(account_url="https://xxxx.blob.core.windows.net", container_name="xxxx", blob_name="SampleSafe.csv", credential="xxxx") data = blob.download_blob(); df = pd.read_csv(data); df1 = df.to_csv(index=False) def read_block(names, igidx=True): pat = r"(\w+),+$\n[^,]+.+?\n,+\n(.+?)(?=\n,{2,})" return pd.concat([ pd.read_csv(StringIO(m.group(2)), skipinitialspace=True) .iloc[:, 1:].dropna(how="all") for m in re.finditer( pat, data.readall(), flags=re.M|re.S) if m.group(1) in names], keys=names, ignore_index=igidx) df2 = read_block(names=["Admissions", "Readmissions"], igidx=False).droplevel(1).reset_index(names="block") print(df2)
错误信息:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
第三次修改及错误
结合实际df1内容再次尝试,仍出现匹配为空的错误,后续还出现类型错误:
df1内容:
Division FacilityName Census Admiss Readmiss Discharges Test1 57 0 0 0 Test3 2 0 0 1 Test5 135 0 0 0 Test6 9 0 0 0 Test4 3 0 0 1 Test2 76 0 0 0 Blindsection 55 1 0 2 Admissions Not Started: 12 Sent: 3 Completed: 3 Division Community ResiName Date DocStatus LastUpdate TestStation Jane Doe 9/12/2023 Sent 9/12/2023 TestStation2 John Doe 9/12/2023 NotStarted Alibaba SuperMan 9/12/2023 NotStarted Iceland SuperWoma 9/12/2023 NotStarted Readmissions Not Started: 1 Sent: 0 Completed: 1 Division Community ResidentName Date DocStatus Last Update StationK PrettyWoman 9/12/2023 Not Started MyGoodness UglyMan 7/21/2023 Completed 7/26/2023 Discharge Division Community ResidentName Date StationKingdom1 PrettyWoman2 8/22/2023 MyGoodness1 UglyMan1 4/8/2023 Landmark2 NiceGuys 9/12/2023 IcelandKingdom2 Mr.Heroshi2 7/14/2023 MoreKingdom2 KingKong 8/31/2023
错误信息:
ValueError: No objects to concatenate
后续错误:
TypeError: expected string or bytes-like object
中文翻译:
TypeError: 期望字符串或类字节对象
解决方案
核心问题分析
- 原正则是针对本地CSV原始文本设计的,将DataFrame转回CSV时,格式与原文件存在差异,导致匹配失败。
- 直接读取Blob二进制数据时,未正确处理文件编码(比如文件是带BOM的UTF-16格式)。
最终可运行代码
import re from io import StringIO import pandas as pd from azure.storage.blob import BlobClient # 初始化Blob客户端 blob = BlobClient( account_url="https://xxxx.blob.core.windows.net", container_name="xxxx", blob_name="SampleSafe.csv", credential="xxxx" ) # 读取Blob原始文本,处理编码(若utf-16不适用,可尝试utf-8-sig、gbk等) data = blob.download_blob() raw_text = data.readall().decode('utf-16') def read_block(names, igidx=True): # 修正正则:匹配块标题+后续表格内容,跳过统计行 pat = r"^(\w+)\s*$\n.*?\n\s*\n(.+?)(?=\n\s*\n|\Z)" matches = [] for m in re.finditer(pat, raw_text, flags=re.M|re.S): block_name = m.group(1) if block_name not in names: continue # 过滤掉带冒号的统计行,只保留表格行 table_lines = [line for line in m.group(2).split('\n') if line.strip() and ':' not in line] if not table_lines: continue # 读取表格为DataFrame df_block = pd.read_csv(StringIO('\n'.join(table_lines)), skipinitialspace=True) matches.append(df_block) if not matches: raise ValueError("未找到匹配的块内容") return pd.concat(matches, keys=names, ignore_index=igidx) # 提取目标块并整理格式 df2 = read_block(names=["Admissions", "Readmissions"], igidx=False) df2 = df2.droplevel(1).reset_index(names="Admission") print(df2)
关键说明
- 编码处理:根据文件实际编码调整
decode的参数,比如带BOM的UTF-8用utf-8-sig,中文文件可能用gbk。 - 正则修正:新正则跳过了块内的统计行(如
Not Started: 12...),只提取有效表格内容,避免无效匹配。 - 避免格式丢失:直接读取Blob原始文本,保留文件的原始换行和分隔格式,确保正则能正确识别块结构。
内容的提问来源于stack exchange,提问作者Java
相关产品推荐
相关产品推荐

