python json表格化输出
阅读原文时间:2023年07月08日阅读:2

需求

  • 将json数据以表格形式输出
  • 超长文本换行输出
  • 能显示中文
  • 在linux终端输出

实现

首先数据的模样。既然是表格化输出,那必然传入的数据是一个数组(废话),如果一个项文本很长需要换行输出,那这个项所属的项组都要换行输出。

首先是处理json数据:

jd = json.loads(data)

这样产生的数据是一个字典列表,即:

[{'key0': '值5', 'key1': '值5', 'key2': '值5', 'key3': '值5', 'key4': '值5'},
{'key0': '值6', 'key1': '值6', 'key2': '值6', 'key3': '值6', 'key4': '值6'},
{'key0': '值7', 'key1': '值7', 'key2': '值7', 'key3': '值7', 'key4': '值7'},
{'key0': '值8', 'key1': '值8', 'key2': '值8', 'key3': '值8', 'key4': '值8'},
{'key0': '值9', 'key1': '值9', 'key2': '值9', 'key3': '值9', 'key4': '值9'}]

定义函数

def tabular_print(datum):

上面说了,咱们先对传进来的数据进行检查:

try:
    if len(datum) == 0:
        print('None.')
        return
except TypeError:
    print('None')
    return

对于每个数据组,统一调用 limit_print(line) 函数来打印。

首先打印表头:

limit_print(keys)

然后打印数据

for item in datum:
    val = []
    for k in keys:
        val.append(item[k])
        limit_print(val)

以下是 limit_print 的实现,仅针对一个汉字是两倍字母宽度的情况。

# 在有限的宽度下进行输出,超长则换行
def limit_print(line):
    flag = True
    max_row_size = 20
    cnt = 0

    length = []
    for s in line:
        length.append(get_length(str(s)))

    lst = [0 for _ in range(len(line))]
    sz = [0 for _ in range(len(line))]

    while flag:
        sod = 0
        for i in range(len(line)):
            s = str(line[i])
            n = length[i]
            if n < max_row_size * cnt:
                sod += 1
                print(' ' * max_row_size, end='')
            else:
                if n > max_row_size * (cnt + 1):
                    lst[i], sz[i] = next_station(s, lst[i], sz[i], max_row_size * (cnt + 1))
                    print(' ' * (max_row_size * (cnt + 1) - sz[i]), end='')
                else:
                    sod += 1
                    lst[i], sz[i] = next_station(s, lst[i], sz[i], n)
                    print(' ' * (max_row_size * (cnt + 1) - sz[i]), end='')
            print(' ', end='')
        if sod == len(line):
            flag = False
        cnt += 1
        print()

    print('-' * (max_row_size + 1) * len(line))

# 获取字符串在屏幕上显示的长度
def get_length(s) -> int:
    res = 0
    for i in s:
        # 中文占两个单位宽度
        if is_full_width(i):
            res += 2
        else:
            res += 1
    return res

# 确定换行位置
def next_station(s, idx, st, ed) -> (int, int):
    while idx < len(s) and st < ed:
        if is_full_width(s[idx]):
            if st + 2 > ed:
                return idx, st
            else:
                st += 2
        else:
            st += 1
        print(s[idx], end='')
        idx += 1
    return idx, st

# 是否是全角符号
def is_full_width(s) -> bool:
    if '\u4e00' <= s <= '\u9fa5':
        return True
    if '\u0f01' <= s <= '\uff60':
        return True
    if '\uffe0' <= s <= '\uffe6':
        return True
    return False