3

私はPythonをまったく初めて使用します。Pythonのcsvモジュールは、Idがやりたいことに最適です。いくつかの異なる方法を試してみましたが、4 番目の (垂直) 列を使用して配列を作成することさえまだできていません。

何百行もある 4 列の csv ファイルがあります。先に進む前に、Python が私がやりたいことをすべて達成できることを確認する必要があります。

  1. csvファイルを読み取り、
  2. FILE の 4 列目 (垂直方向) で COMMAND を実行します

  3. コマンドは印刷します

  4. HEALTHY の各行を読み取ります (COMMAND から)

  5. 新しい 5 列目の HEALTHY を、5 列すべてで NEW_FILE に書き込みます

  6. FILE の最初の空の行までループする

例 FILE (セル ビューではカンマ区切り)

  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'

コマンドの例

  # 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
  --------------------

HEALTHY の複数の行があり、すべてが Yes でない場合、HEALTHY は「No」に等しい

HEALTHY がどの行にも見つからない場合、HEALTHY は「エラー スキャン」に相当します。

これは私がこれまでに持っているものです

  #!/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

上記の実行:

  # 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

おまけ:
stdout/command の出力で何か(linux、swap、NTFS など、上記の問題の 3 番目のコマンドの例) も検索し、それを行 [5] に追加するか、既に追加されている後に次に追加したい場合[i]Healthy[/i] を検索しました... 新しい if ステートメントを開始しようとしましたが、行 [4]、または [i]Healthy[/i] の場合と同じ行のみを追加するように見えます。

また、OR ステートメントの使用方法もわかりません。どこ

 if 'Linux' OR 'swap' OR 'LVM' in stdout:  
     writer.writerow(row + ['Linux']) # for multiple lines/partitions.

 elif 'BSD' in stdout:  
     writer.writerow(row + ['BSD'])

 elif 'NTFS' in stdout:
     writer.writerow(row + ['Windows'])

 else:
     writer.writerow(row + ['Error Scanning'])

最後に、COMMAND 列を PATH に変更し、PATH を実行するようにコマンドを変更しました。これは機能しています。2 番目のコマンドを実行して、PATH のファイルサイズを取得したいと思います。私はいくつかの方法を試しました。

お時間をいただきありがとうございます。これがすべてできることを願っています。

4

2 に答える 2

4

subprocess.Popenを正しく使用していないため、差し迫った問題が発生します ( OSError: [Errno 2] No such file or directory)。

shell=True一般に、Popen の最初の引数は、キーワード パラメータも渡さない限り、文字列ではなくシーケンスにする必要があります。最初の引数が文字列shell=Falseの場合 (デフォルト)、Popen は文字列の値に対応する名前のファイルを実行しようとします。(文字列全体)という名前のファイルがない"python '/root/my_script.py'"ため、OSError.

そう、

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

おそらく次のようになるはずです...

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

または(本質的に同等)

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

または (警告を参照)

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

更新:あなたの質問に対する答えは「はい」です。Python は、やりたいことをすべて達成するのに役立ちます。これがあなたのリストの内訳です。

スポイラー警告!自分で物事を理解したい場合は、この行を超えて読まないでください。

  • read a csv FILE

あなたがしたことは大丈夫です。別の方法 ...

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

...これは、潜在的に新しい概念、with ステートメント、およびリスト内包表記を導入します。しかし、実行する中間リストは実際には必要ありません。同じループで読み取りと書き込みを行うことができます (以下を参照)。

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

コマンドを実行した結果を出力したいと思っているとします。

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'])
    

そして、それをすべてまとめます(テストされていません)...

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'])

更新: csv リーダーおよびライター ファイル オブジェクトの不適切な名前の選択を修正

更新: Python 2.5 でfrom __future__ import with_statementディレクティブが導入されました。2.5 より古いバージョンの Python では、with ステートメントは使用できません。この場合、一般的なアプローチは、ファイル操作を try 最終的にラップすることです。のように、

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()

チッ!

于 2012-04-12T15:01:32.767 に答える
1

あなたの「ボーナス」セクションで:

複数のものを検索したい場合、最も簡単で簡単な方法は、それぞれを個別に検索してから次のように接続することorです。

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

これが洗練されていない、またはさらに検索する必要がある場合は、any関数とジェネレーター式を使用できます。

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

最後に、これでも洗練されていない場合、または stdout が非常に大きくなり、何度も検索したくない場合は、reモジュールを介して正規表現を使用できます。

于 2012-04-13T17:53:40.233 に答える