python json表格化输出
需求
- 将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