2012-04-12 1 views
3

Ich bin völlig neu in Python, ich lese Python CSV-Modul ist ideal für was ich gerne tun würde. Ich habe einige Zeit damit verbracht, verschiedene Methoden auszuprobieren, konnte aber noch nicht einmal ein Array mit der vierten (vertikalen) Spalte erstellen.Python: Csv lesen, Befehl ausführen und Ergebnisse in neue vertikale Spalte schreiben

Ich habe eine vierspaltige CSV-Datei mit Hunderten von Zeilen. Bevor ich fortfahre, sollte ich wahrscheinlich verifizieren, dass Python sogar all das erreichen kann, was ich tun möchte.

  1. Lesen einer CSV-Datei,
  2. Befehl ausführt, auf der vierten (vertikal) Spalte FILE

  3. der Befehl druckt

  4. jede Zeile für gesunde (von COMMAND) lesen

  5. schreiben Sie HEALTHY auf neue fünfte Spalte zu NEW_FILE mit allen fünf Spalten

  6. Schleife, bis erste leere Zeile der Datei

Beispieldatei (comma in Zellansicht begrenzt)

HOST     PLATFORM  ARCH    COMMAND 
    server1     win    x86_64    python '/root/server1.py' 
    server2     linux   x86_64    python '/root/server2.py' 
    server3     linux   x86_64    python '/root/server3.py' 

Beispiel COMMAND

# python '/root/server1.py' 
    -------------------- 
    Error: Could not open /root/server1.py 


    # python '/root/server2.py' 
    -------------------- 
    server2 p1 (NTFS)  output1:100 output:200 HEALTHY:Yes 
    -------------------- 


    # python 'root/server3.py' 
    -------------------- 
    server3 p1 (linux)  output1:100 output:200 HEALTHY:No 
    server3 p2 (linux)  output1:100 output:200 HEALTHY:Yes 
    server3 p3 (swap)  output1:100 output:200 HEALTHY:No 
    -------------------- 

wenn mehrere Linien von gesunden und alle nicht gleich Ja, HEALTHY ist gleich "Nein"

Wenn HEALTHY in keiner Zeile gefunden wird, ist GESUNDHEIT gleich "Error Scannin" g“

Dies ist, was ich

#!/usr/bin/python 
    # 

    import csv 
    import subprocess 

    # read csv file 
    csv_file = open("my_list.csv", "rb") 
    my_csv_reader = csv.reader(csv_file, delimiter=",") 
    my_data_list = [] 
    for row in my_csv_reader: 
      print row 
      my_data_list.append(row) 
    csv_file.close() 

    # write csv file 
    csv_file = open("new_data.csv", "wb") 
    my_csv_writer = csv.writer(csv_file, delimiter=",") 
    for row in my_data_list: 
      my_csv_writer.writerow(row) 
    csv_file.close() 

    # running commands, getting output 
    # run COMMAND column from csv_file, use "python 'my_script.py'" for now 
    # my_script.py only for now: print "HEALTHY:Yes" 
    p = subprocess.Popen("python '/root/my_script.py'",stdout=subprocess.PIPE,stderr=subprocess.PIPE) 
    output, errors = p.communicate() 
    print output 
    print errors 

Ausführen der oben so weit habe:

# python '/root/this_script.py' 
    ['HOST', 'PLATFORM', 'ARCH', 'COMMAND'] 
    ['server1', 'win', 'x86_64', "python '/root/server1.py'"] 
    ['server2', 'linux', 'x86_64', "python '/root/server2.py'"] 
    ['server3', 'linux', 'x86_64', "python '/root/server3.py'"] 
    Traceback (most recent call last): 
    File "thisscript.py", line 24, in ? 
     p = subprocess.Popen('python myscript1.py',stdout=subprocess.PIPE,stderr=subprocess.PIPE) 
    File "/usr/lib64/python2.4/subprocess.py", line 550, in __init__ 
     errread, errwrite) 
    File "/usr/lib64/python2.4/subprocess.py", line 993, in _execute_child 
     raise child_exception 
    OSError: [Errno 2] No such file or directory 

Bonus:
Wenn ich die stdout/Befehlsausgabe für etwas suchen wollte auch (wie Linux, Swap, NTFS, etc, - dritten Beispiel Befehl in Frage oben) und anhängen an Zeile [5], oder nächste, nachdem es bereits gesucht hat f oder [i] Gesund [/ i] ... Ich habe versucht, eine neue if-Anweisung zu starten, aber es scheint nur Zeile [4] anzuhängen, oder dieselbe Zeile wie bei [i] Gesund [/ i].

Ich kann auch nicht herausfinden, wie man eine OR-Anweisung verwendet. Wobei

Zuletzt habe ich die COMMAND-Spalte in den Pfad geändert und den Befehl geändert, um den Pfad auszuführen. Was funktioniert? Ich möchte einen zweiten Befehl ausführen, um die Dateigröße von PATH zu holen. Ich habe ein paar Methoden ausprobiert.

Vielen Dank für Ihre Zeit. Ich hoffe, das kann alles getan werden.

+0

Was passiert, wenn Sie diesen Code ausprobieren? Wenn es sich um Ihre eigentliche Eingabedatei handelt, ist sie nicht durch Kommas getrennt, da sie keine Kommas enthält. –

+0

@ThomasK Ich denke, er hat die CSV für uns einfach verschönert. – KurzedMetal

+0

Rechts, das ist eine Beispielansicht der Zelle eines Kommas begrenzten csv. – Tommy

Antwort

4

Sie verwenden subprocess.Popen nicht richtig, was zu dem unmittelbaren Problem führt (OSError: [Errno 2] No such file or directory).

Im Allgemeinen sollte das erste Argument für Popen eine Sequenz sein, keine Zeichenfolge, es sei denn, Sie übergeben auch den Schlüsselwortparameter shell=True. Wenn das erste Argument eine Zeichenfolge ist und shell=False (Standardeinstellung), versucht Popen, die Datei auszuführen, die nach dem Wert der Zeichenfolge benannt ist. Es gibt keine Datei mit dem Namen "python '/root/my_script.py'" (die gesamte Zeichenfolge), daher erhalten Sie eine OSError.

So

p = subprocess.Popen(
    "python '/root/my_script.py'", 
    stdout=subprocess.PIPE, stderr=subprocess.PIPE 
) 

sollte wohl so etwas wie werden ...

p = subprocess.Popen(
    ["python", "'/root/my_script.py'"], 
    stdout=subprocess.PIPE, stderr=subprocess.PIPE 
) 

oder (im Wesentlichen äquivalent)

p = subprocess.Popen(
    "python '/root/my_script.py'".split(), 
    stdout=subprocess.PIPE, stderr=subprocess.PIPE 
) 

oder (siehe warning)

p = subprocess.Popen(
    "python '/root/my_script.py'", shell=True, 
    stdout=subprocess.PIPE, stderr=subprocess.PIPE 
) 

Update: Die Antwort auf Ihre Frage ist Ja. Python kann Ihnen dabei helfen, alles zu erreichen, was Sie tun möchten. Hier ist eine Aufschlüsselung Ihrer Liste.

SPOILER ALARM! Lies nicht über diese Zeile hinaus, wenn du die Dinge selbst herausfinden willst.

  • read a csv FILE

Was Sie getan haben, ist in Ordnung. Eine andere Art und Weise ...

with open('my_list.csv', 'rb') as fp: 
    my_data_list = [row for row in csv.reader(fp)] 

... die einige potenziell neue Konzepte einführt, die with statement und list comprehensions. Aber Sie brauchen nicht wirklich eine Zwischenliste auf handeln, können Sie in der gleichen Schleife (siehe unten) lesen und schreiben

  • executes COMMAND on fourth (vertical) column of FILE
  • the COMMAND prints
  • loop until first empty row of FILE

I‘ Es wird davon ausgegangen, dass Sie die Ausgabe oder das Ergebnis des Befehls ausgeben möchten.

for row in my_data_list: 
    command = row[3] #<- 4th column is index 3, 1st is 0 
    p = Popen(command.split(), stdout=PIPE, stderr=STDOUT) #<- stderr to stdout 
    stdout, empty = p.communicate() 
    print stdout 
  • read each line for HEALTHY (from COMMAND)
    • if multiple lines of HEALTHY and all do not equal Yes, HEALTHY equals "No"
    • if HEALTHY is not found on any lines, HEALTHY equals "Error Scanning"
  • write HEALTHY on new fifth column to NEW_FILE with all five columns

    if 'HEALTHY:No' in stdout: 
        writer.writerow(row + ['No']) 
    elif 'HEATHLY:Yes' in stdout: 
        writer.writerow(row + ['Yes']) 
    else: 
        writer.writerow(row + ['Error Scanning']) 
    

Und alles zusammensetzen (ungetestet) ...

import csv 
from subprocess import Popen, PIPE, STDOUT 

with open('my_list.csv', 'rb') as incsv: 
    with open('new_data.csv', 'wb') as outcsv: 
     reader = csv.reader(incsv) 
     writer = csv.writer(outcsv) 

     for row in reader: 
      p = Popen(row[3].split(), stdout=PIPE, stderr=STDOUT) 
      stdout, empty = p.communicate() 

      print 'Command: %s\nOutput: %s\n' % (row[3], stdout) 

      if 'HEALTHY:No' in stdout: 
       writer.writerow(row + ['No']) 
      elif 'HEATHLY:Yes' in stdout: 
       writer.writerow(row + ['Yes']) 
      else: 
       writer.writerow(row + ['Error Scanning']) 

Update: Fest schlechte Namenswahl csv-Leser und -Schreiber Datei Objekte

Update: Python 2.5 eingeführt, um die from __future__ import with_statement Richtlinie. Für Versionen von Python älter als 2.5 ist die With-Anweisung nicht verfügbar. In diesem Fall besteht der übliche Ansatz darin, die Dateioperationen schließlich in einen Versuch einzubinden. Wie in,

import csv 
from subprocess import Popen, PIPE, STDOUT 

incsv = open('my_list.csv', 'rb') 
try: 
    reader = csv.reader(incsv) 
    outcsv = open('new_data.csv', 'wb') 
    try:  
     writer = csv.writer(outcsv) 

     for row in reader: 
      p = Popen(row[3].split(), stdout=PIPE, stderr=STDOUT) 
      stdout, empty = p.communicate() 

      print 'Command: %s\nOutput: %s\n' % (row[3], stdout) 

      if 'HEALTHY:No' in stdout: 
       writer.writerow(row + ['No']) 
      elif 'HEATHLY:Yes' in stdout: 
       writer.writerow(row + ['Yes']) 
      else: 
       writer.writerow(row + ['Error Scanning']) 
    finally: 
     outcsv.close() 
finally: 
    incsv.close() 

HTH!

+0

Schön, das hat den letzten Fehler behoben. Jetzt druckt "GESUND: Ja" – Tommy

+1

Ich liebe die SPOILER ALARM :) Wir brauchen mehr von denen auf SO, Menschen sollten es genießen, die Rätsel zu lösen ... – max

+0

Guter Job. Beim Versuch, Ihre Spoiler zu verwenden: File "my_list.py", Zeile 4 mit open ('my_list.csv', 'rb') als incsv: ^ Syntax: ungültige Syntax – Tommy

1

In Ihrem „Bonus“ Abschnitt:

Wenn Sie mehrere Dinge suchen möchten, ist die einfachste und direkteste Weg ist für jeden separat und dann eine Verbindung mit or suchen:

if 'Linux' in stdout or 'swap' in stdout or 'LVM' in stdout: 
    writer.writerow(row + ['Linux']) 

Wenn Sie dieses unelegant finden oder für andere Dinge suchen müssen, können Sie die any Funktion und einen Generator Ausdruck verwenden:

if any(x in stdout for x in ('Linux', 'swap', 'LVM')): 
    writer.writerow(row + ['Linux']) 

Schließlich, wenn dies noch zu unelegant ist, oder wenn stdout viel größer wird und Sie es nicht mehrmals suchen möchten, können Sie reguläre Ausdrücke über das Modul re verwenden.

+0

Danke JonnyY das funktioniert gut – Tommy

Verwandte Themen