You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python解析SWMM模型.inp文件中特殊格式的表头?

解析SWMM .inp文件特殊格式表头的Python方案

我明白你在处理SWMM .inp文件时遇到的头疼问题——那些跨多行、没有固定分隔符的表头确实很难搞,只取最后一行肯定丢失了关键的分类信息。下面我给你一套完整的解决方案,利用SWMM表头的对齐特性(分隔线行)来精准解析完整表头,再提取对应的数据生成DataFrame。

核心思路

SWMM这类特殊表头的关键线索是分隔线行(全由短横线组成的行),它的每个短横线块的宽度正好对应每个表头列的宽度范围。我们可以:

  1. 先定位到目标数据块(SWMM的.inp文件用[SectionName]分块)
  2. 收集所有表头相关行(包括;;开头的分类行、分隔线行)
  3. 用分隔线行确定每个列的宽度边界
  4. 按边界提取每一行的表头内容,合并成完整列名
  5. 用同样的边界分割数据行,生成DataFrame

完整代码实现

import re
import pandas as pd

def parse_swmm_inp_table(inp_fname, section_name):
    # 读取文件并预处理:移除空行和首尾空白
    with open(inp_fname, 'r') as f:
        lines = [line.strip() for line in f if line.strip()]
    
    # 定位目标数据块的起始位置
    section_start = None
    for idx, line in enumerate(lines):
        if line.startswith(f'[{section_name}]'):
            section_start = idx + 1
            break
    if not section_start:
        raise ValueError(f"找不到目标数据块 [{section_name}]")
    
    # 收集所有表头行:包括;;开头的说明行和分隔线行
    header_lines = []
    data_start_idx = section_start
    for idx in range(section_start, len(lines)):
        current_line = lines[idx]
        # 判断是否为表头行:要么是;;开头,要么是纯短横线+空格的分隔线
        if current_line.startswith(';;') or re.fullmatch(r'[- ]+', current_line):
            header_lines.append(current_line)
            data_start_idx = idx + 1
        else:
            # 遇到数据行或下一个数据块标记,停止收集表头
            if current_line.startswith('['):
                break
            else:
                break
    
    # 提取分隔线行(用来确定列宽的关键)
    separator_line = None
    for line in header_lines:
        if re.fullmatch(r'-+', line.replace(' ', '')):
            separator_line = line
            break
    if not separator_line:
        raise ValueError("表头中未找到分隔线行,无法确定列宽")
    
    # 确定每个列的起始和结束索引(从分隔线行的短横线块位置提取)
    col_bounds = [(match.start(), match.end()) for match in re.finditer(r'-+', separator_line)]
    
    # 合并多行列内容,生成完整表头
    column_headers = []
    for start, end in col_bounds:
        header_parts = []
        for line in header_lines:
            # 提取当前列区域的内容,清理多余符号和空格
            part = line[start:end].strip().replace(';;', '').strip()
            if part:
                header_parts.append(part)
        # 合并同一列的多行内容
        full_header = ' '.join(header_parts)
        column_headers.append(full_header)
    
    # 提取数据行:按列宽边界分割每行内容
    data_rows = []
    for idx in range(data_start_idx, len(lines)):
        current_line = lines[idx]
        if current_line.startswith('['):
            # 遇到下一个数据块,停止读取
            break
        row_values = []
        for start, end in col_bounds:
            val = current_line[start:end].strip()
            row_values.append(val)
        data_rows.append(row_values)
    
    # 生成DataFrame
    return pd.DataFrame(data_rows, columns=column_headers)

使用示例

假设你要解析的是.inp文件中的[TIMESERIES]块,只需调用:

# 替换为你的文件路径和目标数据块名称
df = parse_swmm_inp_table('your_swmm_model.inp', 'TIMESERIES')
print(df.head())

关键优势

  • 适配任意行数的表头:不管表头跨2行还是3行,都会自动合并对应列的所有内容
  • 比空格分割更可靠:利用固定宽度分割,避免了数据中含单个空格导致的分割错误
  • 精准定位数据块:通过SWMM的[Section]标记定位,不会误读其他块的内容

内容的提问来源于stack exchange,提问作者Prasanna dahal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:21:22