2016-10-06 6 views
0

Ich habe etwa 5000 .gz-Dateien, aus denen ich die Daten in Form von "Liste der Wörterbücher" extrahieren muss.Python: Erstelle Datei aus der Liste der Wörterbücher

Beispielquelldaten:

{"user" : "J101", "ip" : "192.0.0.0", "usage" : "1000", "Location" : "CA", 
"time" : "12038098048"} 

{"user" : "M101", "ip" : "192.0.0.1", "usage" : "5000", 
"time" : "12038098048", "Device" : "iOS" , "user_type" : "Premium"} 

{"user" : "T101", "usage" : "10", "Location" : "AK","time" : "12038098048"} 

{"user" : "A101", "ip" : "192.0.0.3", "usage" : "2000", 
"time" : "12038098048", "user_type" : "Platinum" } 

{"user" : "T101", "usage" : "10", "Location" : "AK","time" : "12038098048"} 

{"user" : "J101", "ip" : "192.0.0.0", "usage" : "1000", "Location" : "CA", 
"time" : "12038098048" } 

Jede Zeile oben stellt die Daten für ein bestimmtes Ereignis; Benutzer J101 und T101 berichtet Daten zweimal, so dass sie jeweils 2 Zeilen haben.

Ich bin in der Anfangsphase des Schreibens von Code dies, also begann ich durch Extrahieren von Daten aus 1. GZ und versuchen zu sehen, ob ich die Daten von Interesse analysieren und erstellen Sie eine TXT-oder CSV-Datei.

Meine Forderung ist nur wenige Attribute aus diesen Dateien zu erhalten, wie user, ip, time und usage.

Unten ist der Code, den ich schrieb, um die Daten aus .gz-Datei zu extrahieren und die Daten in Form einer Liste von Wörterbüchern zu speichern.

import gzip 
from collections import defaultdict 
import json 
import csv 

e_dict = { 'userid' : { 'e_name' : 'user'}, 
     'ipaddr' : { 'e_name' : 'ip' }, 
     'event_time' : { 'e_name' : 'time' }, 
     'usage_in_mb' : { 'e_name' : 'usage' } 
} 

dict_list = [] 
inputdict = defaultdict(lambda: None) 
count_valueerror = 0 

class parser(object): 
    def read_entries(self): 
     count = 0 
     with gzip.open('testfile.gz', 'r') as test: 
      for row in test: 
       try: 
        # Few rows are empty in the source file and have a new line character 
        if row == "\n": 
         continue 
        else: 
         # Changing the type of each row in file to string type for parsing dictionary 
         row_new = json.loads(row) 
         for key, val in e_dict.iteritems(): 
          if val['e_name'] in row_new: 
           inputdict[key] = row_new[val['e_name']] 
       except ValueError: 
        count_valueerror += 1 
       dict_list.append(inputdict) 

    def create_csv(self): 
     with open('dict.csv', 'wb') as csv_file: 
      for row in dict_list: 
       for key, val in row: 
        csvwriter = csv.DictWriter(csv_file, fieldnames= row.keys(), extrasaction='raise', dialect='excel') 
        csvwriter.writeheader() 
        csvwriter.writerows(val) 
     return csv_file 

Die create_csv Methode funktioniert nicht richtig. Ich bin nicht sicher, wie man das dict_list analysiert und jedes Wörterbuchobjekt nimmt, um es in csv/Textdatei zu schreiben.

Ich bekomme diesen Fehler ValueError: dict contains fields not in fieldnames: 'p für create_csv Methode.

Antwort

0

An einem gewissen Punkt in Ihrem Code haben Sie Zeile in einen String gesetzt, sagen wir,

'{"user" : "J101", "ip" : "192.0.0.0", "usage" : "1000", "Location" : "CA", "time" : "12038098048"}' 

dann zu bekommen, was Sie berechnen möchten,

[eval(row)[_] for _ in ['user', 'ip', 'time', 'usage']] 

ein Ergebnis wie zu erhalten,

['J101', '192.0.0.0', '12038098048', '1000'] 
0

Ich denke, das Problem könnte in Ihrem CSV-Datei-Writer-Methode sein. Sie scheinen den Header der Datei und eine Zeile mit den Daten für jeden Schlüssel jeder Zeile zu schreiben.

Sie können so etwas wie dies versuchen:

def create_csv(dict_list): 
    with open('dict.csv', 'w') as csv_file: 
     # Create writer, using first item's keys as header values 
     csvwriter = csv.DictWriter(csv_file, fieldnames=dict_list[0].keys(), extrasaction='raise', dialect='excel') 

     # Write the header 
     csvwriter.writeheader() 

     # Iterate rows in dictionary list 
     for row in dict_list: 
      # Write row 
      csvwriter.writerow(row) 

    return csv_file 

ich auf meinem Rechner ausprobiert und es funktioniert. Lass es mich wissen, wenn du das brauchst.

+0

Danke Oscar. Lass mich das versuchen. – Himanshu

+0

Es funktioniert gut für den Fall, den ich in der Frage erwähnt habe. Vielen Dank. Aber ich suche nach einem dynamischen Ansatz, da die Anzahl der Spalten/Feldnamen nicht in jeder Zeile gleich ist. Ich möchte die Obermenge aller Feldnamen aus der .gz-Datei. @namwoojin erwähnt hier einen Ansatz mit Listen. Ich werde es jetzt versuchen. Suchen Sie auch nach einer Option, um das Ergebnis mit dict-Objekt zu erhalten. – Himanshu

+0

Die 'fieldnames = dict_list [0] .keys()' in 'fieldnames = e_dict.keys()' wurde geändert und es funktioniert jetzt. Vielen Dank @Oscar. – Himanshu

0

Ändern ...

Zwei Liste, ein Wörterbuch Generation (cveFieldName, eventFieldName, inputdict)

inputdict = {} 
e_list = ('userid', 'user'), ('ipaddr', 'ip'),\ 
     ('event_time', 'time'), ('usage_in_mb', 'usage'),\ 
     ('test_1', 'test1'), ('test_2', 'test2'),\ 
     ('test_3', 'test4'), ('test_5', 'test6') 

cveFieldName, eventFieldName = zip(*e_list) 

eventFieldName Liste verwenden, inputdict.(Clear) löschen

def read_entries(self): 
    count_valueerror = 0 
    with gzip.open('test.gz', 'r') as test: 
     for row in test: 
      try: 
       # Few rows are empty in the source file 
       # and have a new line character 
       if row == "\n": 
        continue 
       else: 
        # Changing the type of each row in file 
        # to string type for parsing dictionary 

        row_new = json.loads(row) 
        for idx, x in enumerate(eventFieldName): 
         inputdict[cveFieldName[idx]] = row_new[x] if x in row_new else '' 
      except ValueError as e: 
       print e 
       count_valueerror += 1 
      dict_list.append(dict(inputdict)) 
      # inputdict.clear() 

cveFieldName Verwendung

def create_csv(self): 
     with open('dict.csv', 'wb') as csv_file: 
      csvwriter = csv.DictWriter(
       csv_file, 
       fieldnames=cveFieldName, 
       extrasaction='raise', 
       dialect='excel') 
      csvwriter.writeheader() 
      for row in dict_list: 
       try: 
        csvwriter.writerow(row) 
       except Exception as e: 
        print e 

     return csv_file 

dict.csv

userid,ipaddr,event_time,usage_in_mb,test_1,test_2,test_3,test_5 
J101,192.0.0.0,12038098048,1000,,,, 
M101,192.0.0.1,12038098048,5000,,,, 
T101,,12038098048,10,,,, 
A101,192.0.0.3,12038098048,2000,,,, 
T101,,12038098048,10,,,, 
J101,192.0.0.0,12038098048,1000,,,, 

inputdict.clear() < = Pflicht Anweisung

def read_entries(self): 
    count_valueerror = 0 
    with gzip.open('test.gz', 'r') as test: 
     for row in test: 
      # import pdb; pdb.set_trace() 

      try: 
       # Few rows are empty in the source file 
       # and have a new line character 
       if row == "\n": 
        continue 
       else: 
        # Changing the type of each row in file 
        # to string type for parsing dictionary 

        row_new = json.loads(row) 
        for key, val in e_dict.iteritems(): 
         if val['e_name'] in row_new: 
          inputdict[key] = row_new[val['e_name']] 
      except ValueError as e: 
       print e 
       count_valueerror += 1 
      dict_list.append(dict(inputdict)) 
      inputdict.clear() # <==== very important 

def create_csv(self): 
    with open('dict.csv', 'wb') as csv_file: 
     csvwriter = csv.DictWriter(
      csv_file, 
      fieldnames=['userid', 'ipaddr', 'event_time', 'usage_in_mb'], 
      extrasaction='raise', 
      dialect='excel') 
     csvwriter.writeheader() 
     for row in dict_list: 
      try: 
       csvwriter.writerow(row) 
      except Exception as e: 
       print e 

    return csv_file 

Ohne die Anweisung: inputdict.clear()

userid,ipaddr,event_time,usage_in_mb 
J101,192.0.0.0,12038098048,1000 
M101,192.0.0.1,12038098048,5000 
T101,192.0.0.1,12038098048,10   <=== M101 ip address 
A101,192.0.0.3,12038098048,2000 
T101,192.0.0.3,12038098048,10   <=== A101 ip address 
J101,192.0.0.0,12038098048,1000 

+0

Danke. Aber oben ist nur eine Beispieldatei. Ich habe mehr als 20 Spalten oder Feldnamen. Ich möchte das dynamisch machen. Gibt es einen Weg, in dem die Feldnamen Werte von einer Obermenge von Schlüsseln in 'InputDict' annehmen können – Himanshu

+0

ok ich sehe, ändern Sie den Code –

+0

Entschuldigung für die Verzögerung in der Antwort. Der obige aktualisierte Code hat super funktioniert. Ich habe auch versucht, was Oscar oben mit einigen Änderungen in den 'Feldnamen' erwähnt und alles funktioniert wie erwartet. Vielen Dank @nam. – Himanshu

Verwandte Themen