Python скрипт, который может сортировать очень большие файлы CSV как по дате, так и по времени, а также учитывает файлы, в которых дата может быть в ДД / ММ / ГГГГ - PullRequest
0 голосов
/ 06 мая 2020

Изначально я написал сценарий, который мог сортировать по дате / времени, который работал хорошо, но потребовал, чтобы я сначала переформатировал даты в 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...