3

我对 python 完全陌生,我读过 python 的 csv 模块非常适合我想做的事情。我花了一些时间尝试几种不同的方法,但还不能使用第四(垂直)列创建数组。

我有一个包含数百行的四列 csv 文件。在我继续之前,我可能应该验证 python 甚至可以完成我想做的所有事情。

  1. 读取 csv 文件,
  2. 在 FILE 的第四(垂直)列上执行 COMMAND

  3. 命令打印

  4. 阅读健康的每一行(来自命令)

  5. 将新的第五列上的 HEALTHY 写入所有五列的 NEW_FILE

  6. 循环直到 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 和 all 不等于 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

奖励:
如果我还想在标准输出/命令输出中搜索某些内容(例如 linux、swap、NTFS 等,--第三个上面有问题的示例命令)并将其附加到第 [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 的命令。哪个正在工作。我想执行第二个命令来获取 PATH 的文件大小。我尝试了几种方法。

感谢您的时间。我希望这一切都能做到。

4

2 回答 2

4

您没有正确使用subprocess.Popen,这导致了直接的问题 ( OSError: [Errno 2] No such file or directory)。

一般来说,Popen 的第一个参数应该是一个序列,而不是一个字符串,除非你还传递了shell=True关键字参数。如果第一个参数是字符串并且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 finally 中。如中,

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

最后,如果这仍然太不优雅,或者如果标准输出变得更大并且您不想多次搜索它,您可以通过re模块使用正则表达式。

于 2012-04-13T17:53:40.233 回答