У меня есть большой файл csv, который я читаю. В зависимости от первых двух значений строки в столбце1 я хочу вывести содержимое в разные файлы csv.
Файл может выглядеть так:
Column1;Column2
01;BE
02;ED
12;FD
14;DS
03;ED
04;DF
Мой код выглядит следующим образом:
import csv
output_path=r'C:\myfolder\large_file.csv'
with open(os.path.join(os.path.dirname(output_path),"column1_01.csv"), "w", encoding = "utf-8", newline='') as \
out_01, open(os.path.join(os.path.dirname(output_path),"column1_02.csv"), "w", encoding = "utf-8", newline='') as \
out_02, open(os.path.join(os.path.dirname(output_path),"column1_03.csv"), "w", encoding = "utf-8", newline='') as \
out_03, open(os.path.join(os.path.dirname(output_path),"column1_04.csv"), "w", encoding = "utf-8", newline='') as \
out_04:
cw01 = csv.writer(out_01, delimiter = ";", quoting=csv.QUOTE_MINIMAL)
cw02 = csv.writer(out_02, delimiter = ";", quoting=csv.QUOTE_MINIMAL)
cw03 = csv.writer(out_03, delimiter = ";", quoting=csv.QUOTE_MINIMAL)
cw04 = csv.writer(out_04, delimiter = ";", quoting=csv.QUOTE_MINIMAL)
with open(output_path, encoding = "utf-8") as in_f:
cr = csv.reader(in_f, delimiter = ";")
cw01.writerow(next(cr))
cw02.writerow(next(cr))
cw03.writerow(next(cr))
cw04.writerow(next(cr))
for line in cr:
if (line[0][:2] = = "01"): cw01.writerow(line)
if (line[0][:2] = = "02"): cw02.writerow(line)
if (line[0][:2] = = "03"): cw03.writerow(line)
if (line[0][:2] = = "04"): cw04.writerow(line)
Теперь моя проблема заключается в том, что когда я добавляю следующую строку, вывод для «05» я получаю остановку итерации ошибки (я проверил ее с помощью выборочных данных, и в ней не так много строк данных, поэтому я думаю, что это должно что-то делать с это). Кроме того, основная проблема заключается в том, что при проверке файлов я вижу, что это не сработало. Он не выводит записи в правильные файлы должным образом. Где моя ошибка?
Думаю проблема может быть во всем следующем(кр). Что я хочу сделать, так это просто использовать заголовок из исходного большого CSV и иметь его для каждого CSV. Заголовок тот же. Мне нужны все файлы в конце с заголовком.
Мне нужно чистое решение csv. Никаких других пакетов.
Я хотел бы найти точную ошибку в моем коде. Почему это не работает и где ошибка? Я не хочу никаких дальнейших изменений, вводящих обработку исключений, таких как try, функции, такие как def или любые другие. Мне не нужно универсальное решение. Я хочу найти конкретную ошибку в моем коде.
Исходный большой файл имеет много столбцов, поэтому заголовок довольно длинный. Поэтому мне нужно решение, в котором мне не нужно вручную вводить все столбцы, чтобы добавить их в заголовок.
Куда мне поместить заголовок = next(cr) ?
Я бы посоветовал cr = csv.reader(in_f, delimiter = ";"); header = next(cr); cw01.writerow(header); ...; cw04.writerow(header);
Пожалуйста, опубликуйте это как ответ, чтобы я мог принять его.
12;FD
- это будет записано в файл или пропущено?
@wwii Это будет пропущено.
Что происходит, когда вы это делаете? Я перетасовал ваш код, чтобы сделать его универсальным, так что вы можете указать любой список cols, и он создаст 1 выходной файл для каждого столбца и найдет столбец в словаре авторов csv.
import csv
output_path = r'C:\myfolder\large_file.csv'
def get_fhandle(col_name):
return open(
os.path.join(os.path.dirname(output_path), f"column1_{col_name}.csv"),
"w", encoding = "utf-8", newline=''
)
cols = ["01", "02", "03", "04", "05"]
files = {col: get_fhandle(col) for col in cols}
try:
writers = {
col: csv.writer(file, delimiter = ";", quoting=csv.QUOTE_MINIMAL)
for col, file in files.items()
}
with open(output_path, encoding = "utf-8") as in_f:
cr = csv.reader(in_f, delimiter = ";")
header = next(cr)
for writer in writers.values():
writer.writerow(header)
for line in cr:
col = line[0][:2]
if col not in writers:
raise ValueError(
f"'{col}' is not a known column. Should be: {cols.join(', ')}"
)
writers[col].writerow(line)
finally:
for file in files.values():
file.close()
Нет, извини, но это не то, чего я хочу. Я хотел бы найти точную ошибку в моем коде. Почему это не работает и где ошибка? Я не хочу никаких дальнейших изменений, вводящих обработку исключений, таких как try, функции, такие как def или любые другие. Мне не нужно универсальное решение. Я хочу найти конкретную ошибку в моем коде.
Хорошо, удачи с этим! Затем устраните неполадки в коде с помощью отладчика или распечатки.
В том, как я обрабатываю заголовок со следующим, есть ошибка, но я не знаю, почему. Я должен добавить его в каждый CSV-файл, в который я пишу, но так он не работает, так как у меня слишком много следующего.
Использование contextlib.ExitStack() позволяет существенно навести порядок, особенно если мы настроим небольшой словарь, чтобы сопоставить, какие ключи в нашей карте ввода с тем, в какой выходной файл мы хотим записать.
import contextlib
import csv
files_out = {
"01": "column1_01.csv",
"02": "column1_02.csv",
"03": "column1_03.csv",
"04": "column1_04.csv",
}
with contextlib.ExitStack() as stack:
## ---------------------
## Set up a bunch of csv writers
## ---------------------
writers = {
key: csv.writer(stack.enter_context(open(value, "w", newline = "")))
for key, value
in files_out.items()
}
## ---------------------
file_in = stack.enter_context(open("small.csv"))
rows = csv.reader(file_in, delimiter = ";")
## ---------------------
## write a header to each output file
## ---------------------
headers = next(rows)
for writer in writers.values():
writer.writerow(headers)
## ---------------------
## ---------------------
## write rows to the appropriate file
## ---------------------
for row in rows:
key = row[0]
if not key in writers:
print(f"no file defined for key {key}")
continue
writers[key].writerow(row)
## ---------------------
Чтобы ответить на ваш конкретный вопрос о том, почему ваш код в настоящее время не работает, давайте посмотрим на:
with open(output_path, encoding = "utf-8") as in_f:
cr = csv.reader(in_f, delimiter = ";")
cw01.writerow(next(cr))
cw02.writerow(next(cr))
cw03.writerow(next(cr))
cw04.writerow(next(cr))
for line in cr:
if (line[0][:2] = = "01"): cw01.writerow(line)
if (line[0][:2] = = "02"): cw02.writerow(line)
if (line[0][:2] = = "03"): cw03.writerow(line)
if (line[0][:2] = = "04"): cw04.writerow(line)
Здесь:
cw01.writerow(next(cr))
По существу записывает первую строку (заголовок) вашего входного файла в первый выходной файл. Затем мы повторяем это, записывая последовательные строки ввода в выходные данные.
После записи первых 4 строк ввода в одну строку в каждом из четырех выходов мы затем читаем оставшиеся строки во входном файле (последние две в примере) и записываем их в файлы 3 и 4 по мере необходимости.
Итак, вашим конкретным решением было бы использовать next() один раз, чтобы получить заголовок из вашего входного файла, а затем записать его в каждый из ваших выходных файлов:
with open(output_path, encoding = "utf-8") as in_f:
cr = csv.reader(in_f, delimiter = ";")
headers = next(cr)
cw01.writerow(headers)
cw02.writerow(headers)
cw03.writerow(headers)
cw04.writerow(headers)
for line in cr:
if (line[0][:2] = = "01"): cw01.writerow(line)
if (line[0][:2] = = "02"): cw02.writerow(line)
if (line[0][:2] = = "03"): cw03.writerow(line)
if (line[0][:2] = = "04"): cw04.writerow(line)
Встроенная функция Python next Получить следующий элемент из итератора, вызвав его __next__() метод. Таким образом, итератор перемещается вперед к следующему элементу. Следовательно, вы вызываете next много раз, чтобы получить заголовок.
[...]
with open(output_path, 'r', encoding = "utf-8") as in_f:
cr = csv.reader(in_f, delimiter = ";")
header = next(cr)
cw01.writerow(header)
cw02.writerow(header)
cw03.writerow(header)
cw04.writerow(header)
for line in cr:
[...]
Надеюсь, это поможет.
Для заголовка используйте header = next(cr), чтобы избежать повторения cr