编辑:https://stackoverflow.com/a/644314/8520561不能解决问题,可能是因为我放下了一个键,代码有误,我听不懂或者是以上所有原因。
我已经编辑了下面脚本的末尾,以显示什么给了我正确答案。
作为强迫自己学习python的一种练习,我想用它创建一些有用的东西。我正在尝试在python中尽可能正确地做到这一点。不允许作弊,例如使用Unix命令行工具来避免几行python。
我想打开一个CSV文件,然后从输入文件的第7行开始,将其写入具有不同标题的另一个CSV文件中。第六行定义输入标题。我以为它们总是一样。
输入标头位于CS_headers中,输出标头位于YNAB_headers
# Define the headers for the bank statement input file
CS_headers = ['Booking Date', 'Text', 'Debit', 'Credit', 'Balance']
# Define the headers for the YNAB output file
YNAB_headers = ['Date', 'Payee', 'Memo', 'Inflow', 'Outflow']
我想地图
'Booking Date'
→'Date'
'Text'
→'Payee'
'Debit'
→'Outflow'
'Credit'
→'Inflow'
从输出中删除'Balance'
有时
在'Memo'
字段中注入内容。
脚本输出
$ ./cs_statement.py
Traceback (most recent call last):
File "./cs_statement.py", line 52, in <module>
statementwriter.writerow(row)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/csv.py", line 155, in writerow
return self.writer.writerow(self._dict_to_list(rowdict))
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/csv.py", line 151, in _dict_to_list
+ ", ".join([repr(x) for x in wrong_fields]))
ValueError: dict contains fields not in fieldnames: 'Booking Date', 'Debit', 'Balance', 'Text', 'Credit'
输入文件的前几行。
$ $ head -8 statement.csv | cat -n
1 Created on 30.06.2019 12:14:06 CEST
2 Bookings
3 Account,"Private account Bonviva Silver,CH72 0483 5028 1234 5678 0,John Doe, Swisstown"
4 Balance,"CHF 37,924.81"
5 Booking Entries from 05.07.2018 - 30.06.2019
6 Booking Date,Text,Debit,Credit,Balance
7 28.06.2019,"Payment domestic - ISR ,Salt Mobile SA ,AID5c9fdb2ae4744b9ba7ad22afbd16b17d,Salt Mobile SA,Rue du Caudray 4 1020 Renens 1,UBS Switzerland AG,Bahnhofstrasse 45 8098 Zürich CH ",19.00,,37924.81
8 28.06.2019,"Payment domestic - ISR ,Mortgage Q2 2019 ,DNCS-20190615-IXN0-TXN0,Mortgage Q2 2019,SP-29312538-0,SWISS LIFE AG,ZUERICH ",806.25,,
目前的脚本。
#!/usr/local/bin/python3
import csv
import re
# Credit Scheiß's idea of a CSV file includes:
# 1 the first 3 characters are non-ASCII
# 2 the CSV headers are on line 6
# 3 the last line is a totals line
def skip_lines(handle, numlines):
for i in range(0, numlines):
handle.readline()
lines_to_skip = 5
in_filename = 'bankstatement.csv'
out_filename = 'bankstatement.YNAB.csv'
# Define the headers for the bank statement input file
CS_headers = ['Booking Date', 'Text', 'Debit', 'Credit', 'Balance']
# Define the headers for the YNAB output file
YNAB_headers = ['Date', 'Payee', 'Memo', 'Inflow', 'Outflow']
# open the file and skip to the heaeder line
statement_infile_handle = open(in_filename, 'r', newline='')
skip_lines(statement_infile_handle, lines_to_skip)
# what kind of CSV file am I?
dialect = csv.Sniffer().sniff(statement_infile_handle.read(10240))
statement_infile_handle.seek(0)
skip_lines(statement_infile_handle, lines_to_skip)
# define a CSV reader object to, er, read the file
statementreader = csv.DictReader(statement_infile_handle,
fieldnames=CS_headers, restkey='',
dialect=dialect)
# define a CSV writer, so I stand a chance of getting at the headers
statement_outfile_handle = open(out_filename, 'w', newline='')
# statementwriter = csv.writer(statement_outfile_handle)
statementwriter = csv.DictWriter(statement_outfile_handle,
fieldnames=YNAB_headers, restval='',
dialect=dialect)
statementwriter.writeheader()
# This part
# for row in statementreader:
# statementwriter.writerow(row)
#
# was replaced with this, to solve the problem.
keymap = {'Booking Date': 'Date', 'Text': 'Payee',
'Debit': 'Outflow', 'Credit': 'Inflow'}
for row in statementreader:
outrow = {keymap[key]: value for key, value in row.items() if key in
keymap}
statementwriter.writerow(outrow)
答案 0 :(得分:1)
您想将旧键映射到新键,对自己I want to map something
说时,请考虑字典。您需要为每行创建一个新的字典。
...
newkeys = {'Booking Date':'Date','Text':'Payee',
'Debit':'Outflow','Credit':'Inflow'}
for row in statementreader:
newrow = {newkeys[key]:value for key,value in row.items() if key in newkeys}
statementwriter.writerow(newrow)
也可以这样写:
for row in statementreader:
newrow = {}
for key,value in row.items():
if key in newkeys:
newrow[newkeys[key]] = value
statementwriter.writerow(newrow)
或
for row in statementreader:
newrow = {}
for key,value in row.items():
try:
newrow[newkeys[key]] = value
except KeyError:
pass
statementwriter.writerow(newrow)