J'essaye de lire un fichier csv et d'écrire le contenu basé sur les 2 premières colonnes à l'intérieur, avec un numéro de séquence. Tout cela fonctionne bien .. Mais mon défi est d'ajouter les fichiers au lieu d'écrire de nouveaux fichiers pour chaque ligne.

test.csv

2002,2402,1,1,1,1,1,1,1,1
2002,2002,2,2,2,2,2,2,2,2
2402,2402,3,3,3,3,3,3,3,3
2002,2402,4,4,4,4,4,4,4,4
3333,2402,5,5,5,5,5,5,5,5
3333,3333,6,6,6,6,6,6,6,6

Fichiers de sortie:

2002_200418_000000001.csv
1,1,1,1,1,1,1,1
2002_200418_000000002.csv
2,2,2,2,2,2,2,2
2002_200418_000000003.csv
4,4,4,4,4,4,4,4
2402_200418_000000001.csv
1,1,1,1,1,1,1,1
2402_200418_000000002.csv
3,3,3,3,3,3,3,3
2402_200418_000000003.csv
4,4,4,4,4,4,4,4
2402_200418_000000004.csv
5,5,5,5,5,5,5,5
3333_200418_000000001.csv
5,5,5,5,5,5,5,5
3333_200418_000000002.csv
6,6,6,6,6,6,6,6

python code:

import os, csv, datetime
from itertools import cycle

seq = {'2002': cycle(range(1,999)),'2402': cycle(range(1,999)),'3333': cycle(range(1,999))}

def SequenceNum(f):
    return f'{next(seq[f])}'.zfill(9)

def filegenerate(X):
    with open(X) as csvfile:
        timestamp = '_' + '{:%y%m%d%H%M%S}'.format(datetime.datetime.now()) + '_'
        reader = csv.reader(csvfile, quotechar="'")
        for cdr in reader:
            if cdr[0] == '' and cdr[1] == '':
                pass
            elif cdr[0] == cdr[1]:
                with open(cdr[0] + timestamp + SequenceNum(cdr[0]) + '.csv', 'a', newline='') as f:
                    writer = csv.writer(f, quotechar="'")
                    writer.writerow(cdr[2:])
                    f.close()
            elif cdr[0] != cdr[1] and cdr[1] != '' and cdr[0] != '':
                with open(cdr[0] + timestamp + SequenceNum(cdr[0]) + '.csv', 'a', newline='') as f:
                    writer = csv.writer(f, quotechar="'")
                    writer.writerow(cdr[2:])
                    f.close()
                with open(cdr[1] + timestamp + SequenceNum(cdr[1]) + '.csv', 'a', newline='') as f:
                    writer = csv.writer(f, quotechar="'")
                    writer.writerow(cdr[2:])
                    f.close()
            elif cdr[1] != '' and cdr[0] == '':
                with open(cdr[1] + timestamp + SequenceNum(cdr[1]) + '.csv', 'a', newline='') as f:
                    writer = csv.writer(f, quotechar="'")
                    writer.writerow(cdr[2:])
                    f.close()
            elif cdr[0] != '' and cdr[1] == '':
                with open(cdr[0] + timestamp + SequenceNum(cdr[0]) + '.csv', 'a', newline='') as f:
                    writer = csv.writer(f, quotechar="'")
                    writer.writerow(cdr[2:])
                    f.close()

if __name__ == '__main__':
    filegenerate('test.csv')

À partir de la sortie ci-dessus, le fichier 2002 est généré plusieurs fois en fonction du nombre de lignes, je veux ajouter des lignes au fichier correspondant .. veuillez aider à améliorer mon code.

expected output:

2002_200418_000000001.csv
1,1,1,1,1,1,1,1
2,2,2,2,2,2,2,2
4,4,4,4,4,4,4,4

2402_200418_000000001.csv
1,1,1,1,1,1,1,1
3,3,3,3,3,3,3,3
4,4,4,4,4,4,4,4
5,5,5,5,5,5,5,5

3333_200418_000000001.csv
5,5,5,5,5,5,5,5
6,6,6,6,6,6,6,6

Je pense que ce problème est dû à la numérotation seq attribuée lors de l'écriture du fichier, peut-être que je peux ajouter toutes les lignes dans les fichiers 2002..etc et les renommer plus tard avec le numéro seq .. MAIS Y A-T-IL UNE MEILLEURE APPROCHE ??

Pour les questions soulevées pourquoi seq est requis, lorsque chaque fichier se termine par 000000001, c'est parce que lorsque je itère sur plusieurs fichiers .csv, la numérotation des séquences sera attribuée et incrémentée davantage.

example:
test1.csv
test2.csv
test3.csv

output:
2002_200418_000000001.csv
2402_200418_000000001.csv
3333_200418_000000001.csv

2002_200418_000000002.csv
2402_200418_000000002.csv
3333_200418_000000002.csv

2002_200418_000000003.csv
2402_200418_000000003.csv
3333_200418_000000003.csv

Mon idée, le numéro seq devrait être attribué par rapport à chaque .csv mais pas par rapport à chaque ligne des fichiers csv. Veuillez aider ...

Merci d'avance.

0
Sheldon 18 avril 2020 à 11:05

2 réponses

Meilleure réponse

Il s'agit d'une approche dans laquelle le contenu futur du fichier est collecté dans un dictionnaire avant d'être écrit sur le disque. Pour chaque fichier futur, une entrée est faite dans le dictionnaire qui contient un ensemble avec les lignes du fichier. J'ai choisi un ensemble parce que j'ai supposé que si vous rencontriez le même contenu dans les colonnes> = 3, vous ne vouliez qu'il soit écrit une fois dans la sortie. Vous pouvez remplacer l'ensemble par une liste, si ce n'est pas le cas.

import os, csv, datetime
from itertools import cycle

seq = { '2002': cycle(range(1,999)),
        '2402': cycle(range(1,999)),
        '3333': cycle(range(1,999)) }

def SequenceNum(f):
    return f'{next(seq[f])}'.zfill(9)

def filegenerate(filePath: str) -> None:
    with open(filePath, 'r') as csvFile:
        rows = [row for row in csv.reader(csvFile, quotechar="'")]

    fileContents = dict()
    for row in rows:
        fileContents.setdefault(row[0], set()).add(','.join(row[2:]) + '\n')
        fileContents.setdefault(row[1], set()).add(','.join(row[2:]) + '\n')

    timestamp = '_' + '{:%y%m%d%H%M%S}'.format(datetime.datetime.now()) + '_'
    for key in fileContents:
        lines = list(fileContents[key])
        lines.sort()
        with open(str(key) + timestamp + SequenceNum(key) + '.csv', 'w') as f:
            f.writelines(lines)

if __name__ == '__main__':
    filegenerate('test.csv')

Ce code produit les fichiers suivants avec votre test.csv fourni:

2002_200418103658_000000001.csv

1,1,1,1,1,1,1,1
2,2,2,2,2,2,2,2
4,4,4,4,4,4,4,4

2402_200418103658_000000001.csv

1,1,1,1,1,1,1,1
3,3,3,3,3,3,3,3
4,4,4,4,4,4,4,4
5,5,5,5,5,5,5,5

3333_200418103658_000000001.csv

5,5,5,5,5,5,5,5
6,6,6,6,6,6,6,6
0
Stefan Scheller 18 avril 2020 à 08:52

IIUC, utilisez:

def SequenceNum(seq):
    return f'{seq}'.zfill(9)

def write_file(n, data, seq):
    filename = n + '_' + datetime.datetime.now().strftime("%y%m%d") + '_' + SequenceNum(seq) + '.csv'
    with open(filename, 'a', newline='') as f:
        writer = csv.writer(f, quotechar="'")
        writer.writerow(data)

def read_files():
    files = ["test1.csv", "test2.csv", "test3.csv"]

    for idx, filename in enumerate(files, 1): # process each file one by one
        with open(filename, "r") as file:
            reader = csv.reader(file)
            for line in reader:
                n1, n2, *data = line
                write_file(n1, data, idx)
                if n1 != n2:
                    write_file(n2, data, idx)

Appel de la fonction:

read_files()

Cela crée les fichiers suivants:

2002_200418_000000001.csv
2402_200418_000000001.csv
3333_200418_000000001.csv

2002_200418_000000002.csv
2402_200418_000000002.csv
3333_200418_000000002.csv

2002_200418_000000003.csv
2402_200418_000000003.csv
3333_200418_000000003.csv
1
Shubham Sharma 18 avril 2020 à 09:02