Изначально я написал сценарий, который мог сортировать по дате / времени, который работал хорошо, но потребовал, чтобы я сначала переформатировал даты в CSV с ДД / ММ / ГГГГ на ГГГГММДД, используя RegEx в TextPad, что было нормально, но это было довольно медленно переформатировать файлы таким образом. Затем мне также пришлось отменить этот процесс в TextPad, чтобы вернуть даты в исходный формат.
Затем я попытался написать что-то, что могло бы переформатировать дату (как для входных, так и для выходных файлов). как сортировка, которая вроде как сработала. Проблема возникает, когда я пытаюсь запустить это в большом файле и получаю ошибку памяти.
Это мой код, который работает, но очень неуклюжий и требует много времени для выполнения. Некоторая помощь была бы очень признательна!
Я знаю, что мне не нужно писать промежуточный файл «Reformat_Dates.csv», но я не мог понять, как заставить его работать в противном случае.
"""
Run using:
python csvsort.py 'input file.csv' 4 5 ## where 4 and 5 are the columns to be sorted (excel style so column 1 is 1)
Will create a sorted file with _sorted suffix.
"""
import sys
import os
import csv
from sys import argv
from operator import itemgetter
import re
from datetime import datetime
num_arguments = len(argv)
lines = []
# open file as read-only
with open(argv[1], "r", newline='') as raw_dates:
reader = csv.reader(raw_dates)
# go over all of its rows, and the row's items and change
# items that match the date format
for row in reader:
for i, string in enumerate(row):
if re.match(r"\d{2}\/\d{2}\/\d{4}", string):
datetimeobject = datetime.strptime(string, '%d/%m/%Y')
new_string = datetimeobject.strftime('%Y%m%d')
row[i] = new_string
# save edited, and originally correct ones to new list
new_row = row
lines.append(new_row)
# write new rows by overwriting original file
with open('reformat_Dates.csv', "w", newline='') as in_formatted:
writer = csv.writer(in_formatted)
writer.writerows(lines)
# Check usage and provide help
if num_arguments == 2 and argv[1] in ('-h', '-help'):
print("Usage: %s input_file.csv 1st_sort_col ... nth_sort_col" % argv[0])
print("Example: %s foo.csv 1 2 -9" % argv[0])
print("\tSorts foo.csv on 1st and 2nd columns (ascending) then 9th descending.")
sys.exit()
elif num_arguments < 3: # Guidance on arguments to pass
usage = "Usage: %s input_file.csv 1st_sort_col ... nth_sort_col" % argv[0]
error = "You passed only %d arguments" % num_arguments
sys.exit("%s -- %s" % (usage, error))
if '.csv' not in argv[1]: # Ensure using a CSV file
usage = "Usage: %s input_file.csv 1st_sort_col ... nth_sort_col" % argv[0]
error = "You passed %r for input_file.csv" % argv[1]
sys.exit("%s -- %s" % (usage, error))
# Create the output file as input with _sorted before .csv extension
input_file = 'reformat_Dates.csv'
original_File = argv[1]
output_file = original_File.replace('.csv', '_sorted.csv')
# Ensure you can open the source and target files
try:
source = open(input_file, 'r',newline='')
except:
e = sys.exc_info()[0]
sys.exit("Error - Could not open input file %r: %s" % (input_file, e))
try:
target = open(output_file, 'w',newline='')
except:
e = sys.exc_info()[0]
sys.exit("Error - Could not open output file %r: %s" % (output_file, e))
print("\nSorting data from %r into %r, inside out" % (input_file, output_file))
# Now create a list of sorting tuples where the first item is the index of
# the data object you wish to sort and the second item is the type of sort,
# Ascending (Reverse is False) or Descending (Reverse is True)
sorts = []
for i in range (2, num_arguments): # Skip script name and input filename
# Ensure you are passed Excel-like column numbers
try:
sort_arg = int(argv[i])
except:
e = sys.exc_info()[0]
sys.exit("Error - Sort column %r not an integer: %s." % (argv[i], e))
if sort_arg == 0:
sys.exit("Error - Use Excel-like column numbers from 1 to N")
# Create a tuple for each as described above
if sort_arg > 0:
sorts.append((sort_arg - 1, False)) # Convert column num to index num
else:
sorts.append(((-1 * sort_arg) - 1, True))
# Read in the data creating a label list and list of one tuple per row
reader = csv.reader(source)
row_count = 0
data=[]
for row in reader:
row_count += 1
# Place the first row into the header
if row_count == 1:
header = row
continue
# Append all non-header rows into a list of data as a tuple of cells
data.append(tuple(row))
for sort_step in reversed(sorts):
print("Sorting Column %d (%s) Descending=%s" % \
(sort_step[0] + 1, header[sort_step[0]], sort_step[1])) # +1 for Excel col num
data = sorted(data, key=itemgetter(sort_step[0]), reverse=sort_step[1])
print("Done sorting %d data rows (excluding header row) from %r" % \
((row_count - 1), input_file))
# Now write all of this out to the new file
writer = csv.writer(target)
writer.writerow(header) # Write the header in CSV format
for sorted_row in data: # Wrtie the sorted data, converting to CSV format
writer.writerow(sorted_row)
print('Done writing %d rows (sorted data plus header) to %r\n' % \
(row_count, output_file))
source.closed
target.closed
raw_dates.closed
in_formatted.closed
final = []
# open file as read-only
with open(output_file, "r", newline='') as final_data:
reader = csv.reader(final_data)
# go over all of its rows, and the row's items and change
# items that match the date format
for row in reader:
for i, string in enumerate(row):
if re.match(r"\d{8},", string):
datetimeobject = datetime.strptime(string,'%Y%m%d')
new_string = datetimeobject.strftime('%d%m%Y')
row[i] = new_string
# save edited, and originally correct ones to new list
new_row = row
print(new_row)
final.append(new_row)
# write new rows by overwriting original file
print(final)
with open('Final_Dates.csv', "w", newline='') as final_output:
writer = csv.writer(final_output)
writer.writerows(final)
# Close the files
source.closed
target.closed