Skip to main content
 首页 » 编程设计

python之将 csv 输入文件打印到列/行表中

2025年05月04日10arxive

我正在尝试编写一个程序(除其他外)将输入文件('table1.txt')打印成如下所示的格式。

其中 diff 是每行的第 3 个值和第 4 个值之间的差值。

我想我已经弄清楚了基本的想法并且我尝试这样做:

f = open("table1.txt",'r') 
 
for aline in f: 
    values = aline.split(',') 
    print('Team:',values[0],', Points:',values[1],', Diff:',values[2]-values[3],'Goals:',values[2])  
 
f.close() 

但它会导致操作数类型错误。我想我只需要更改迭代文件中项目的方式,但我不知道该怎么做。

请您参考如下方法:

你绝对应该为此使用 csv 模块。它允许您遍历行和值(本质上是构建一个奇特的“列表列表”)。 csv 也有一个 DictWriter 对象,可以很好地将这些数据吐到一个文件中,但实际显示它有点不同。让我们先看看如何构建 csv。

import csv 
import operator 
 
with open('path/to/file.txt') as inf, 
     open('path/to/output.csv', 'wb') as outf: 
    reader = sorted(csv.reader(inf), key=operator.itemgetter(1) 
    # sort the original data by the `points` column 
 
    header = ['Team', 'Points', 'Diff', 'Goals'] 
    writer = csv.DictWriter(outf, fieldnames=header) 
 
    writer.writeheader()  # writes in the fieldnames 
    for row in reader: 
        if not len(row) == 4: 
            break  # This is probably not a useful row 
        teamname, points, home_g, away_g = row 
        writer.writerow({'Team': teamname, 
                         'Points': points, 
                         'Diff': home_g - away_g, 
                         'Goals': "{:>2} : {:2}".format(home_g, away_g) 
                         }) 

这应该会为您提供一个 csv 文件(位于 path/to/output.csv),其中包含您请求的格式的数据。此时,只需提取数据并运行 print 语句来显示它就非常容易了。我们可以使用字符串模板来很好地做到这一点。

import itertools 
 
row_template = """\ 
{{0:{idx_length}}}{{<1:{teamname_length}}}{{>2:{point_length}}}{{>3:{diff_length}}}{{=4:{goals_length}}}""" 
 
with open('path/to/output.csv') as inf:  # same filename we used before 
    reader = csv.reader(inf)  # no need to sort it this time! 
    pre_process, reader = itertools.tee(reader) 
    # we need to get max lengths for each column to build our table, so 
    # we will need to iterate through twice! 
    columns = zip(*pre_process)  # this is magic 
    col_widths = {k: len(max(col, key=len)) for k,col in zip( 
        ['teamname_length', 'point_length', 'diff_length', 'goals_length'], 
        columns)} 

值得停下来看看这个魔法。我不会深入探讨 columns = zip(*pre_process) 魔法惯用语,只是要注意它将列的行变成行的列。也就是说

zip(*[[1, 2, 3], 
      [4, 5, 6], 
      [7, 8, 9]]) 

成为

     [[1, 4, 7], 
      [2, 5, 8], 
      [3, 6, 9]] 

之后,我们只是使用字典理解来构建 {'team_length': value, 'point_length': ...} 等我们可以将其输入到我们的模板中以制作字段宽度合适的尺寸。

等等!

我们还需要那个字典中的idx_length!我们只能通过 len(rows)//10 来计算。不幸的是我们已经用完了我们的迭代器并且我们没有更多的数据。这需要重新设计!我实际上并没有很好地计划这个,但是看到这些事情在编码过程中是如何发生的是很好的说明。

import itertools 
 
row_template = """\ 
{{0:{idx_length}}}{{<1:{teamname_length}}}{{>2:{point_length}}}{{>3:{diff_length}}}{{=4:{goals_length}}}""" 
 
with open('path/to/output.csv') as inf:  # same filename we used before 
    reader = csv.reader(inf) 
    pre_process, reader = itertools.tee(reader) 
 
    # fun with pre-processing for field length! 
    columns = zip(*pre_process) 
 
    keys = ['teamname_length', 'point_length', 'diff_length', 'goals_length'] 
    col_widths = {k:0 for k in keys} 
    for key, column in zip(keys, columns): 
        col_widths['idx_length'] = max([col_widths['idx_length'], len(column) // 10 + 1]) 
        col_widths[key] = max((col_widths[key],max([len(c) for c in column))) 
 
    col_widths['idx_length'] += 1  # to account for the trailing period 
 
    row_format = row_template.format(**col_widths) 
    # puts those field widths in place 
 
    header = next(reader) 
    print(row_format("", *header))  # no number in the header! 
    for idx, row in enumerate(reader, start=1):  # let's do it! 
        print(row_format("{}.".format(idx), *row)) 

(几乎)包含电池

但我们不要忘记 Python 有广泛的第 3 方模块可供选择。一个完全满足您的需求。 tabulate将采用格式良好的表格数据并为其吐出一个 pretty-print ascii 表。正是您要尝试做的事情

通过命令行从 pypi 安装它

$ pip install tabulate 

然后导入您的显示文件并打印。

import tabulate 
 
with open('path/to/output.csv') as inf: 
    print(tabulate(inf, headers="firstrow")) 

或者直接从输入跳到打印:

import csv 
import operator 
import tabulate 
 
with open('path/to/file.txt') as inf: 
    reader = sorted(csv.reader(inf), key=operator.itemgetter(1)) 
    headers = next(reader) 
    print(tabulate([(row[0], row[1], row[2]-row[3], 
                     "{:>2} : {:2}".format(row[2], row[3])) for row in reader], 
                   headers=headers))