这是我的代码:
import csv
import os
for root, subFolders, files in os.walk('/path/to/folder/'):
if 'routes.csv' in files:
with open(os.path.join(root, "R.csv"), "r") as inf, \
open(os.path.join(root, "B.csv"), "a") as output:
reader = csv.DictReader(inf, quotechar='"')
headers = ["R_id"]
writer_B_routes = csv.DictWriter(output, headers,
extrasaction='ignore')
writer_B_routes.writeheader()
for row in reader:
if int(row["R_type"]) == 3:
writer_B_routes.writerow(row)
当我在我的CSV文件夹上运行此操作时,如果R_id
的值仅为数字,则输出为B.csv
罚款(即。1234
)。但是,如果R_id
的值是字母数字(即A123
),那么我在B.csv
中获得的输出为""
。
我尝试将int(row["R_type"]) == 3
更改为str()
,认为Dialect的构建方式存在一些问题,但这不起作用。我不确定这个数据只传递一个整数。
更新:链接到示例数据+脚本:Here
更新2:我已经测试了一些其他样本 - 案例似乎是独一无二的,但我无法确定原因。我有另一组包含R_id
005M1
的示例数据,但它运行正常。给我这个问题的数据有R_id
E2
和类似的。但现在我知道它不适用于所有字母数字ID。
答案 0 :(得分:3)
请注意,以下内容是指代码中RemoveBAIO.py
代码中显示的代码。
问题是您尝试读取的routes.csv
文件是一个Unicode文本文件,其开头是UTF-8 Byte-Order-Mark(或BOM),正在被提取csv
模块 - 它无法处理Python 2中的Unicode输入,在documentation中注明 - 作为第一个字段的名称,因此它不是"route_id"
它的"\xef\xbb\xbfroute_id"
。
以下是代码的略微修改版本,显示了处理可能初始BOM的文件的正确方法。它通过将codecs.open()
与'utf-8-sig'
编码结合使用来实现此目的。此编码在codecs
模块的文档的Encodings and Unicode部分中进行了描述。解码时,将跳过任何存在的BOM和编码,它将首先写入3字节的BOM序列。在下面的代码中,它故意仅用于读取输入文件(我解释了为什么进一步下来)。结果是输入文件中的第一个字段名称没有搞砸。
另请注意,我已将int
检查中的转化移至'route_type'
,因此如果遇到包含非数字字符的异常,则不会引发ValueError
异常。
bus_route_ids.csv
上面有一个领先的BOM。添加一个会很复杂,因为数据可能会附加到它上面,因此添加BOM必须以文件是否已存在为条件。 FWIW,我还注意到routes.csv
不是正确的UTF-8,因为它在最后一行中嵌入了\xa0
字符,其序数值大于128.
import codecs
import csv
import os
path_to_folder = '/insert/path/'
with open('hasfares.txt', 'w') as hf:
for root, subFolders, files in os.walk(path_to_folder):
if 'fare_rules.csv' in files:
hf.write('%s\n' % root)
if 'routes.csv' in files:
routes_path = os.path.join(root, 'routes.csv')
bus_route_ids_path = os.path.join(root, 'bus_route_ids.csv')
appending_to_existing_file = os.path.exists(bus_route_ids_path)
with codecs.open(routes_path, 'r', 'utf-8-sig') as inf, \
open(os.path.join(root, "bus_route_ids.csv"), "a") as output:
reader = csv.DictReader(inf, quotechar='"')
headers = ['route_id']
writer_bus_routes = csv.DictWriter(output, headers,
extrasaction='ignore')
if not appending_to_existing_file:
writer_bus_routes.writeheader()
for row in reader:
if row['route_type'] == '3':
writer_bus_routes.writerow(row)
生成的bus_route_ids.csv
文件(假设它尚不存在):
route_id
E1
E2
N
N1
N2
N3
170
S1
S2
S3
S4
W1
W2
W3
W4
C
答案 1 :(得分:0)
尝试
row["R_type"] == "3"
如果R_type是字母数字,那么它的类型是字符串。而3是一个int。
Python不会将int值3隐式解析为字符串,并且在字符串和int之间进行==比较将始终返回false。要修复它,你要么使用字符串版本“3”,要么将3投射到字符串str(3)。
如果R_type可以从CSV解析为int或字符串,你还应该添加一个显式强制转换,以便始终强制转换为字符串,这样就不会出现任何误报。
例如:
str(row["R_type"]) == "3"