编写一个 Python 脚本,按列打印票证
Write a Python script that prints tickets in columns
我正在努力编写一个 Python 脚本来处理文件并生成包含票证的输出文本文件,其格式可通过点阵打印机进行打印。作为参考,我还附上了生成的文本文件应该是什么样子的示例。
ConcertTickets.txt 和
ConcertTickets_result.txt
我的主要问题是设计解决此问题的方法。我不知道如何逐列打印。我能够读取文件,逐行打印,进行验证并使用新名称写入文件。我不确定如何处理 layout_name、列、column_width、column_spacing、left_margin、行间距和 line_item,我能做的最好的是ljust() 用于票之间的左边距。
我不希望有人为我做这项工作,但非常感谢有关使用和不使用第三方包的架构方法的提示。
输入的音乐会门票文件由包含格式信息的 header 和包含实际门票的 body 组成。
header行如下:
- download_datetime - 下载文件的日期和时间
- order_datetime - 订票的日期和时间
- layout_name - 用于格式化工单的布局名称
- columns - 每页宽度的工单列数
- column_width - 每张票栏的宽度
- column_spacing - 工单列之间的 space 秒数
- left_margin - 第一票列左侧的前导 space
- row_spacing - 门票之间的水平线数
- line_item - 行项目表示工单元素必须如何出现在
门票,例如PIN 码在顶部,后面是两个空行,然后是描述、序列号和有效期。订单项的有效值为:pin、描述、serial_number、expiry_date 和空 (space)
- ticket_summary - 每张票据摘要包含票据描述,后跟文件中该类型的票据编号和票据的总面值,例如"Gold 10.00,10,100.00" 表示文件中有 10 张价值 $100.00 的黄金 $10.00 门票
- ticket_fields - 工单字段指示出现在后面的工单数据中的字段及其顺序。这是 header 的最后一行,此行之后的所有数据都应解释为 body 数据,即 CSV 类型格式的实际门票
脚本还需要通过检查文件 body 中的实际工单数量是否与文件 header 中的工单摘要值匹配来进行一些基本的文件验证。如果文件验证失败,程序必须退出并显示适当的错误消息。
生成的输出文件名必须与输入文件名相同,但在文件扩展名之前附加单词“_result”。例如。如果输入文件名是 ConcertTickets.txt 那么输出文件名必须是 ConcertTickets_result.txt
我还需要为脚本开发一套测试用例。
这是我到目前为止的代码
data = []
data_description = []
data_pin = []
data_serial_number = []
data_expiry_date = []
tickets_in_body = 0
# read file from line 19 and create two-dimensional array
result_f = open('ConcertTickets.txt')
for each_line in result_f.readlines()[18:]:
(description, pin, serial_number, expiry_date) = each_line.split(',')
data_description.append(description)
data_pin.append(pin)
data_serial_number.append(serial_number)
data_expiry_date.append(expiry_date.replace("\r\n",""))
tickets_in_body += 1
data = [data_description, data_pin, data_serial_number, data_expiry_date]
# ticket validation and writing to file
result_golden_summary = open('ConcertTickets.txt')
golden_summary = result_golden_summary.readlines()
(golden_description, golden_summary_amount, golden_summary_value) = (golden_summary[15 - 1]).split(',')
if int(golden_summary_amount) != tickets_in_body:
print('The ticket summary in the header does not match the amount of tickets in body')
else:
(filename, extension) = (result_f.name).split('.')
result_f = open(filename + "_result.txt", 'w')
for row in data:
result_f.write("".join(str(item).ljust(25) for item in row))
result_f.close()
这是打开(和关闭)文件的推荐方式:
# open file as read ('r')
with open('ConcertTickets.txt', 'r') as file:
for line in file.readlines()[18:]:
# your logic
# open result file as write ('w'), '+' creates the file if not exist
with open('ConcertTickets_result.txt', 'w+' as file:
# your logic
这里有一些代码供您使用:
import math
result_f = open('ConcertTickets.txt')
all_lines_arr = []
for each_line in result_f.readlines()[18:]:
(description, pin, serial_number, expiry_date) = each_line.split(',')
line_dict = {}
line_dict["description"] = description
line_dict["pin"] = pin
line_dict["serial_number"] = serial_number
line_dict["expiry_date"] = expiry_date.strip()
all_lines_arr.append(line_dict)
per_row = 5
line_space = 30
rows = math.ceil(len(all_lines_arr)/per_row)
for i in range(0, rows):
row_val = (i*per_row)+per_row
if (row_val > len(all_lines_arr)):
row_val = row_val - (row_val-len(all_lines_arr))
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["pin"] + (line_space-(len(all_lines_arr[j]["pin"]))%line_space)*" ", end="")
print("\n"*2)
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["description"] + (line_space-(len(all_lines_arr[j]["description"]))%line_space)*" ", end="")
print()
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["serial_number"] + (line_space-(len(all_lines_arr[j]["serial_number"]))%line_space)*" ", end="")
print()
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["expiry_date"] + (line_space-(len(all_lines_arr[j]["expiry_date"]))%line_space)*" ", end="")
print("\n"*5)
首先我们读取这些行,并将它们放入一个字典数组中,即每个数组元素都是一个字典,它有一个可寻址的值,例如description
接下来,我们使用 per_row
来决定每行打印多少张票(您可以更改)。
然后代码将打印数组中每个元素的字典值。
格式化的关键是它使用模数 %
来打印正确的空格数。我使用 30 作为分隔符。
我删除了您的很多代码,以便为您进行打印格式化。您可以自行修改它以打印到文件或执行您需要的任何其他操作。
根据我的喜好,它有点过于硬编码,但在不知道更多关于您需要什么的情况下,它适用于您的简单案例。
希望对您有所帮助!
我正在努力编写一个 Python 脚本来处理文件并生成包含票证的输出文本文件,其格式可通过点阵打印机进行打印。作为参考,我还附上了生成的文本文件应该是什么样子的示例。
ConcertTickets.txt 和 ConcertTickets_result.txt
我的主要问题是设计解决此问题的方法。我不知道如何逐列打印。我能够读取文件,逐行打印,进行验证并使用新名称写入文件。我不确定如何处理 layout_name、列、column_width、column_spacing、left_margin、行间距和 line_item,我能做的最好的是ljust() 用于票之间的左边距。
我不希望有人为我做这项工作,但非常感谢有关使用和不使用第三方包的架构方法的提示。
输入的音乐会门票文件由包含格式信息的 header 和包含实际门票的 body 组成。
header行如下:
- download_datetime - 下载文件的日期和时间
- order_datetime - 订票的日期和时间
- layout_name - 用于格式化工单的布局名称
- columns - 每页宽度的工单列数
- column_width - 每张票栏的宽度
- column_spacing - 工单列之间的 space 秒数
- left_margin - 第一票列左侧的前导 space
- row_spacing - 门票之间的水平线数
- line_item - 行项目表示工单元素必须如何出现在 门票,例如PIN 码在顶部,后面是两个空行,然后是描述、序列号和有效期。订单项的有效值为:pin、描述、serial_number、expiry_date 和空 (space)
- ticket_summary - 每张票据摘要包含票据描述,后跟文件中该类型的票据编号和票据的总面值,例如"Gold 10.00,10,100.00" 表示文件中有 10 张价值 $100.00 的黄金 $10.00 门票
- ticket_fields - 工单字段指示出现在后面的工单数据中的字段及其顺序。这是 header 的最后一行,此行之后的所有数据都应解释为 body 数据,即 CSV 类型格式的实际门票
脚本还需要通过检查文件 body 中的实际工单数量是否与文件 header 中的工单摘要值匹配来进行一些基本的文件验证。如果文件验证失败,程序必须退出并显示适当的错误消息。
生成的输出文件名必须与输入文件名相同,但在文件扩展名之前附加单词“_result”。例如。如果输入文件名是 ConcertTickets.txt 那么输出文件名必须是 ConcertTickets_result.txt
我还需要为脚本开发一套测试用例。
这是我到目前为止的代码
data = []
data_description = []
data_pin = []
data_serial_number = []
data_expiry_date = []
tickets_in_body = 0
# read file from line 19 and create two-dimensional array
result_f = open('ConcertTickets.txt')
for each_line in result_f.readlines()[18:]:
(description, pin, serial_number, expiry_date) = each_line.split(',')
data_description.append(description)
data_pin.append(pin)
data_serial_number.append(serial_number)
data_expiry_date.append(expiry_date.replace("\r\n",""))
tickets_in_body += 1
data = [data_description, data_pin, data_serial_number, data_expiry_date]
# ticket validation and writing to file
result_golden_summary = open('ConcertTickets.txt')
golden_summary = result_golden_summary.readlines()
(golden_description, golden_summary_amount, golden_summary_value) = (golden_summary[15 - 1]).split(',')
if int(golden_summary_amount) != tickets_in_body:
print('The ticket summary in the header does not match the amount of tickets in body')
else:
(filename, extension) = (result_f.name).split('.')
result_f = open(filename + "_result.txt", 'w')
for row in data:
result_f.write("".join(str(item).ljust(25) for item in row))
result_f.close()
这是打开(和关闭)文件的推荐方式:
# open file as read ('r')
with open('ConcertTickets.txt', 'r') as file:
for line in file.readlines()[18:]:
# your logic
# open result file as write ('w'), '+' creates the file if not exist
with open('ConcertTickets_result.txt', 'w+' as file:
# your logic
这里有一些代码供您使用:
import math
result_f = open('ConcertTickets.txt')
all_lines_arr = []
for each_line in result_f.readlines()[18:]:
(description, pin, serial_number, expiry_date) = each_line.split(',')
line_dict = {}
line_dict["description"] = description
line_dict["pin"] = pin
line_dict["serial_number"] = serial_number
line_dict["expiry_date"] = expiry_date.strip()
all_lines_arr.append(line_dict)
per_row = 5
line_space = 30
rows = math.ceil(len(all_lines_arr)/per_row)
for i in range(0, rows):
row_val = (i*per_row)+per_row
if (row_val > len(all_lines_arr)):
row_val = row_val - (row_val-len(all_lines_arr))
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["pin"] + (line_space-(len(all_lines_arr[j]["pin"]))%line_space)*" ", end="")
print("\n"*2)
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["description"] + (line_space-(len(all_lines_arr[j]["description"]))%line_space)*" ", end="")
print()
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["serial_number"] + (line_space-(len(all_lines_arr[j]["serial_number"]))%line_space)*" ", end="")
print()
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["expiry_date"] + (line_space-(len(all_lines_arr[j]["expiry_date"]))%line_space)*" ", end="")
print("\n"*5)
首先我们读取这些行,并将它们放入一个字典数组中,即每个数组元素都是一个字典,它有一个可寻址的值,例如description
接下来,我们使用 per_row
来决定每行打印多少张票(您可以更改)。
然后代码将打印数组中每个元素的字典值。
格式化的关键是它使用模数 %
来打印正确的空格数。我使用 30 作为分隔符。
我删除了您的很多代码,以便为您进行打印格式化。您可以自行修改它以打印到文件或执行您需要的任何其他操作。
根据我的喜好,它有点过于硬编码,但在不知道更多关于您需要什么的情况下,它适用于您的简单案例。
希望对您有所帮助!