Seite 3 von 5
Re: Dateinamen in jede Zeile schreiben
Verfasst: Freitag 5. Dezember 2014, 10:28
von kidchino
Hey zusammen,
ich hab jetzt das Skript und wollte nun doch jede Datei einzelt ändern und nicht alles in eine Datei packen. Da würde ich gern den Ursprungsnamen nehmen und einen Zusazu dran hängen (bspw: "_nameappend"), aber ich bekomme es nicht hin. Habe jetzt eine Datei (new.csv) die jedes Mal geöffnet wird, aber natürlich auch jedes Mal überschrieben wird. Jemand eine Idee?
So ist das Skript mit dem new.csv-Platzhalter:
Code: Alles auswählen
import csv, os, sys
pfad = 'C:/Skripttesten/papererweiterung/1/' # relevanter Pfad mit Dateien
liste_dateiname = os.listdir(pfad) # Pfad zu den txt/csv Dateien 'Pfad'
csv.field_size_limit(250000)
#gesamte_datei = open('C:/papererweiterung1/Gesamt61.csv', "wb") #öffne die gesamte Datei
for dateiname in liste_dateiname: # für jedes Element der Variable path
liste = [] #erstellt eine leeres Array
neue_datei = open('C:/Skripttesten/papererweiterung/2/new.csv', "wb") #öffne die gesamte Datei
with open(os.path.join(pfad, dateiname), "rb") as f: #öffnet die jeweilige datei
reader = csv.reader(f, delimiter="\t") #liest die zeilen aus, tabstop getrennt
next(reader) #überspringt jeweils die erste zeile
liste = [] #erstellt eine leeres Array
for row in reader:
......
writer = csv.writer(neue_datei, delimiter = "\t").writerows(liste)
Ich dachte, dass sowas in der Art doch gehen müsste:
Code: Alles auswählen
neue_datei = open('C:/Skripttesten/papererweiterung/2/ ‘dateiname + “_new“ .csv', "wb
LG
Kid
Re: Dateinamen in jede Zeile schreiben
Verfasst: Dienstag 6. Januar 2015, 18:38
von kidchino
Hi zusammen,
ich mal wieder

Aktuell nutze ich das Skript:
Code: Alles auswählen
# -*- coding: utf-8 -*-
#Das Skript hängt den Datennamen an jedes Datei eines Ordner hinten dran (4 Zellen) und nennt die Datei um
#!/usr/bin/env python
from __future__ import absolute_import, division, print_function
import csv, os, sys, re
from tempfile import NamedTemporaryFile
pfad = 'C:/Skripttesten/papererweiterung1/60Spalten/' # relevanter Pfad mit Dateien
liste_dateiname = os.listdir(pfad) # Pfad zu den txt/csv Dateien 'Pfad'
csv.field_size_limit(250000)
#gesamte_datei = open('C:/Skripttesten/papererweiterung1/Gesamt60.csv', "wb") #öffne die gesamte Datei
def main():
for dateiname in liste_dateiname:
full_name = os.path.join(pfad, dateiname)
temporary_file = NamedTemporaryFile(
prefix=dateiname, dir=pfad, delete=False
)
with temporary_file:
with open(full_name) as csv_file:
compid, nummer, _, subname = dateiname.split("#")
csv.writer(temporary_file, delimiter="\t").writerows(
row + [""] + [dateiname] + [compid] + [nummer] + [subname] #"splittet" den namen mit der Trennung "#"
for row in csv.reader(csv_file, delimiter="\t")
)
os.rename(temporary_file.name, full_name + "_nameadded")
if __name__ == '__main__':
main()
print("Ende - leere Spalte (wegen 60 Spalten anstelle von 61), Dateiname, CompID, Nr und Suchstring wurde bei jeder Zeile ergaenzt und speichert in", pfad)
In diese Zeile
Code: Alles auswählen
row + [""] + [dateiname] + [compid] + [nummer] + [subname] #"splittet" den namen mit der Trennung "#"
füge ich ja in jede Zeile einen leere Wert und die zusätzlichen vier Werte ein. Nun wollte ich aber zusätzlich noch etwas hinzufügen, aber leider klappt es nicht.
An der 58. Stelle jede Zeile steht soetwas ("wos:12184a21878f921") und ich möchte das "wos:" entfernen und die ID als einen zusätzliche Wert hinten dran setzen.
Also eigentlich so:
Code: Alles auswählen
for row in csv_file:
paperIdOhneWos = row[58].replace ("wos:", "")
row + [""] + [dateiname] + [compid] + [nummer] + [subname] + [paperIdOhneWos ]#"splittet" den namen mit der Trennung "#"
Aber leider geht es nicht.
Der erste Zeichen nach
am Anfang der Zeile wird immer als Fehler markiert.
Jemand eine Idee?
kid
Re: Dateinamen in jede Zeile schreiben
Verfasst: Dienstag 6. Januar 2015, 18:49
von BlackJack
@kidchino: Im Quelltext hast Du einen Generatorausdruck stehen, bei dem neuen Fragment aber eine ``for``-Schleife. Du hast jetzt nicht eine ``for``-Schleife an die Stelle eines Arguments in einem Funktionsaufruf geschrieben, oder? Das ist syntaktisch nicht möglich, da dürfen nur Ausdrücke stehen die zu einem Wert ausgewertet werden können. Eben der Wert der dann als Argument an den Aufruf übergeben wird.
Lauter Listen mit jeweils nur einem Element mit ``+`` zusammenfügen ist auch eine nette Idee. Wie kommt man denn bitte auf so etwas? Erstell da doch bitte *eine* Liste welche die Elemente enthält und ”addiere” diese *eine* Liste an `row`.
Re: Dateinamen in jede Zeile schreiben
Verfasst: Dienstag 6. Januar 2015, 19:09
von kidchino
@Blackjack.
Danke für die schnelle Antwort.
Diesen Teil hab ich von Dir.
Dann hab ich einfach weiter ausprobiert und andere Teile drangehängt.
kidchino hat geschrieben:Lauter Listen mit jeweils nur einem Element mit ``+`` zusammenfügen ist auch eine nette Idee. Wie kommt man denn bitte auf so etwas?
Da ich leider außer 1/2 Jahr Informatik (Turbo Pascal) in der 7. Klasse (ist auch schon ein, zwei Tage her) noch nie groß mit Programmieren in Berührung gekommen bin, probiere ich es halt irgendwie aus. Und wenn ich die Daten in der Datenbank habe, bin ich hoffentlich durch.
So wie das Skript im Moment läuft, macht es ja glaube ich das was es soll. Ich kann natürlich bei 4GB Textdateien nicht jeden einzelnen Datensatz testen, also denke ich nur, dass alles läuft.
Gibt es denn ein Problem so wie ich es gemacht habe oder ist es einfach nur unüblich und wenig effizient?
VG
kid
Re: Dateinamen in jede Zeile schreiben
Verfasst: Dienstag 6. Januar 2015, 20:46
von BlackJack
@kidchino: Den Teil hast Du ziemlich sicher nicht von mir, ausser ich war high oder besoffen.

Re: Dateinamen in jede Zeile schreiben
Verfasst: Dienstag 6. Januar 2015, 20:50
von kidchino
Und eigentlich auch das gesamte Grundgerüst des Skriptes ist von Dir - (1 Seite, 6. Beitrag)
Prosit!
Re: Dateinamen in jede Zeile schreiben
Verfasst: Dienstag 6. Januar 2015, 21:04
von EyDu
Da hast du wohl zu früh angestoßen

Das passiert nämlich, wenn man blind Code übernimmt und nicht versteht was dieser macht.
konkateniert die Liste ``row`` und die Liste ``[dateiname]``. Nun könnte es natürlich sein, dass die zweite Liste auch mehr als ein Element enthalten kann
Code: Alles auswählen
row + ["", dateiname, compid, nummer, subname, paperIdOhneWos ]
Re: Dateinamen in jede Zeile schreiben
Verfasst: Dienstag 6. Januar 2015, 21:19
von kidchino
@EyDu
Danke für die Hilfe.
Aber wieso ist das nun besser? Weniger Fehlerpotential, oder warum?
Re: Dateinamen in jede Zeile schreiben
Verfasst: Dienstag 6. Januar 2015, 21:25
von BlackJack
@kidchino: Weil das andere einfach total hässlicher Murks ist der für jede ``+``Operation eine neue Liste erstellt, da die Elemente der alten Liste und das eine Element der neuen Liste hinein kopiert, dann immer die einelementige Liste wieder wegwirft, und ab dem zweiten ``+`` auch die alte Liste mit den ganzen Elementen wegwirft, und das Spielchen dann mit dem nächsten ``+``-Operator noch mal losgeht.
Re: Dateinamen in jede Zeile schreiben
Verfasst: Dienstag 6. Januar 2015, 21:27
von kidchino
Ok danke.
Re: Dateinamen in jede Zeile schreiben
Verfasst: Donnerstag 8. Januar 2015, 14:24
von kidchino
Hi zusammen,
ich bin immer noch bzw. schon wieder an dieser Stelle:
kidchino hat geschrieben:
Code: Alles auswählen
def main():
for dateiname in liste_dateiname:
full_name = os.path.join(pfad, dateiname)
temporary_file = NamedTemporaryFile(
prefix=dateiname, dir=pfad, delete=False
)
with temporary_file:
with open(full_name) as csv_file:
compid, nummer, _, subname = dateiname.split("#")
csv.writer(temporary_file, delimiter="\t").writerows(
row + ["" + dateiname + compid + nummer + subname]
for row in csv.reader(csv_file, delimiter="\t")
)
os.rename(temporary_file.name, full_name + "_nameadded")
if __name__ == '__main__':
main()
print("Ende - leere Spalte (wegen 60 Spalten anstelle von 61), Dateiname, CompID, Nr und Suchstring wurde bei jeder Zeile ergaenzt und speichert in", pfad)
Bevor hier die eine Liste an row angehängt bzw. die beiden Listen konkateniert [EyDu] werden, möchte ich gern alle Anführungszeichen aus row entfernen.
So klappt es ja normalerweise:
Aber natürlich nicht hier.
Rein logisch müsste es doch zwischen
und
Also alle Anführungszeichen entfernen nach dem Öffnen aber vor dem schreiben. Würde ja Sinn machen, aber es kommt folgender Fehler:
local variable 'row' referenced before assignment
Ich überlege gerade eine globale Variablen draus zumachen, allerdings weiß ich gar nicht ob das sinnvoll ist.
Jemand ein Idee.
LG
kid
Re: Dateinamen in jede Zeile schreiben
Verfasst: Donnerstag 8. Januar 2015, 14:55
von Sirius3
@kidchino: Die Anführungszeichen werden normalerweise vom csv-Reader interpretiert, bzw. wenn nötig vom csv-Writer geschrieben. Wenn Du daran etwas änderst, machst Du Deine Datei kaputt. Die Beiträge von EyDu und Blackjack solltest Du nochmal lesen.
Re: Dateinamen in jede Zeile schreiben
Verfasst: Donnerstag 8. Januar 2015, 15:12
von kidchino
@Sirius3: Das Problem ist, dass ich häufig Werte in einer Liste habe, die Text sind und wo dann Wörrter in Anführungszeichen sind, aber leider fehlerhaft, nämlich bspw. so:
Das ist ein "rotes' ' Haus. (also zwei ' anstelle eines ").
Und wenn das vorkommt, wird das:
falsch --> row + ["" + dateiname + compid + nummer + subname] <--falsch
richtig ist -->
nicht richtig ausgeführt, bzw. gar nicht ausgeführt. Wahrscheinlich ja weil das Anführungszeichen nicht geschlossen wird.
Ich hab sonst keine Idee, wie ich sonst mit diesem Fehler umgehen soll.
Sirius3 hat geschrieben:Die Beiträge von EyDu und Blackjack solltest Du nochmal lesen.
Das verstehe ich nicht. Ich denke, dass dies nun mit nur eine Liste ist ["" + dateiname + compid + nummer + subname] richtig ist.
LG
Re: Dateinamen in jede Zeile schreiben
Verfasst: Donnerstag 8. Januar 2015, 15:24
von BlackJack
@kidchino: Doch das wird ausgeführt und auch ”richtig”, dem Ausdruck ist es völlig egal ob die Einzelteile Anführungszeichen oder sonst was enthalten. Der Ausdruck selbst ist aber sehr wahrscheinlich nicht das was Du willst weil der etwas macht als Dein Ursprünglicher Code und auch als das was EyDu gezeigt hat. Das ist eine Liste bei Dir, aber was glaubst Du denn wie viele Elemente die enthält und wie genau der Inhalt aussieht‽ Was haben die Werte dort für einen Typ und was bewirkt der ``+``-Operator bei diesem Typ‽
Was die Anführungszeichen angeht musst Du Dir mal klarmachen wie das CSV-Format aufgebaut ist. Wie Trennzeichen (Feld und Datensatz) innerhalb von Feldern geschützt werden, wie die Zeichen zum Schützen von Trennzeichen für Felder und Datensätze selber innerhalb von Feldern dargestellt werden (müssen), und so weiter. Und dann müsstest Du das mit dem Dateiformat vergleichen welches das Werkzeug zum Importieren der Daten in die MySQL-Datenbank erwartet. Diese Formate müssen ganz offensichtlich zusammen passen damit das klappt, also muss man dafür sorgen das Dein Programm das schreibt was dieses Werkzeugen lesen möchte und das dieses Werkzeug das lesen kann was von Deinem Programm geschrieben wird. Und das wird man eher nicht durch raten hinbekommen. Höchstens zufällig, und dann weiss man immer noch nicht ob es tatsächlich geklappt hat, oder irgendwelche Fehler kommentarlos verschluckt wurden und Datensätze unvollständig sind oder fehlen.
Re: Dateinamen in jede Zeile schreiben
Verfasst: Donnerstag 8. Januar 2015, 15:25
von Sirius3
kidchino hat geschrieben:Das verstehe ich nicht. Ich denke, dass dies nun mit nur eine Liste ist ["" + dateiname + compid + nummer + subname] richtig ist.
Dann Schau EyDus letzten Beitrag nochmal genau an!
Wenn Du keine korrekten Inputdaten hast, kannst Du nicht das csv-Modul zum Lesen benutzen, bzw. solltest Du Dir zuerst ein Programm schreiben, das die Daten überprüft und gegebenenfalls korrigiert.
Überprüfen heißt, alle Zeilen, die seltsam aussehen, ausgeben lassen und sich überlegen, ob man den Fehler automatisiert korrigieren kann, oder es weniger Aufwand ist, das von Hand zu tun.
Erst wenn Du korrekte Inputdaten hast, kannst Du damit weiterarbeiten. Wenn Du versuchst, mit kaputten Daten zu arbeiten, wirst Du bei jedem weiteren Schritt wieder und wieder auf die Schnauze fallen. Viel Spaß dabei.
Re: Dateinamen in jede Zeile schreiben
Verfasst: Donnerstag 8. Januar 2015, 15:39
von kidchino
Danke euch beiden.
Mist, ja klar.
Ich hatte das von Hand nachgetragen, es muss natrülich ["", dateiname, compid, nummer, subname] heißen.
Sorry!
Sirius3 hat geschrieben:oder es weniger Aufwand ist, das von Hand zu tun.
Es sind ca. 920 falsche Datensätze (Zeilen)dabei, wo ein Fehler auftritt. Per Hand wird das leider nichts.
BlackJack hat geschrieben: klarmachen wie das CSV-Format aufgebaut ist.
Ich bin mir gar nicht sicher, ob es wirklich CSV-Dateien sind. Wenn ich sie mir in Notepad++ ansehe, eine Zeile dann so aussehen: "Wert1" \t "Wert2" \t "Wert3" \t "Wert4" \n\r
Oder sehe ich die Anführungszeichen nicht?
VG
PS
Ich kann auch mal eine Originaldatei vor und nach dem Skript anhängen, wenn es sinnvoll ist.
Dort sind dann nämlich Zeilen wo diese Sachen nicht geschrieben werden ("", dateiname, compid, nummer, subname), also noch vor der MySQL-Datenbank
Re: Dateinamen in jede Zeile schreiben
Verfasst: Donnerstag 8. Januar 2015, 16:39
von kidchino
kidchino hat geschrieben:
Ich bin mir gar nicht sicher, ob es wirklich CSV-Dateien sind.
CSV heißt doch erstmal nur, dass die Werte (dem Namen entsprechend Komma-getrennt) oder mit nem anderen Trennzeichen getrennt sind. Bei mir halt Tabstop. Aber wann werden denn die Werte in Anführungszeichen gesetzt?
Ich bin mir ziemlich sicher, dass im rohen Inhalt meiner Dateien nur störende Anführungszeichen sind, also keine inhaltlich relevanten.
Oder werde die Anführungszeichen gesetzt, während die Dateien durch Python laufen?
VG
Re: Dateinamen in jede Zeile schreiben
Verfasst: Donnerstag 8. Januar 2015, 19:09
von BlackJack
@kidchino: Auch wenn es keinen formalen, verbindlichen Standard gibt, bedeuten Anführungszeichen normalerweise dass alles zwischen den Anführungszeichen der Feldinhalt ist. Das ist zum Beispiel dann wichtig wenn innerhalb des Feldes das Trennzeichen für Felder oder Datensätze vorkommt. Wenn man aber Anführungszeichen im Feldinhalt selbst hat, dann muss man die ja auch noch irgendwie gesondert Kennzeichnen damit die nicht mit den Anführungszeichen um den Feldinhalt verwechselt werden können.
Wie gesagt es gibt keinen Standard, aber ein RFC mit Status ”Entwurf” und eine Arbeitsgruppe beim W3C die auch an einer Spezifikation sitzen, und eben den Quasi-Standard wie ihn viel Software die CSV-Dateien liest und schreibt definiert. Siehe auch
https://en.wikipedia.org/wiki/Comma-separated_values
Re: Dateinamen in jede Zeile schreiben
Verfasst: Donnerstag 8. Januar 2015, 19:21
von kidchino
Okay.
Aber dann kann ich doch einfach alle löschen oder nicht? Ich müsste doch auch alle "x"`s löschen können. Unabhängig von der Sinnhaftigkeit.
Oder kann ich die Anführungszeichen nicht einfach ignorieren als Feldmarkierung?
Re: Dateinamen in jede Zeile schreiben
Verfasst: Donnerstag 8. Januar 2015, 21:01
von BlackJack
@kidchino: So grundsätzlich kannst Du nicht alle Anführungszeichen löschen ohne den Inhalt zu verändern. Ich hatte doch gerade beschrieben welchen Zweck die erfüllen. ``"a","b,c","d"`` ist nicht das selbe wie ``a,b,c,d``. Das erste sind drei Felder, das zweite sind vier Felder. Ähnliches gilt für
vs.
Das erste ist *ein* Datensatz mit drei Feldern, das zweite sind zwei Datensätze mit jeweils zwei Feldern.