【问题标题】:Issues calling awk from within Python using subprocess.call使用 subprocess.call 从 Python 中调用 awk 的问题
【发布时间】:2016-11-03 18:04:38
【问题描述】:

在 Python 中调用 awk 时遇到一些问题。通常,我会执行以下操作以从命令行调用 awk 中的命令。

  1. 打开命令行,无论是否处于管理员模式。
  2. 把我的目录改成awk.exe,即cd R\GnuWin32\bin
  3. 致电awk -F "," "{ print > (\"split-\" $10 \".csv\") }" large.csv

我的命令用于将large.csv文件根据第10列拆分成若干个名为split-[COL VAL HERE].csv的文件。我运行这个命令没有问题。我尝试使用 subprocess.call() 在 Python 中运行相同的代码,但我遇到了一些问题。我运行以下代码:

def split_ByInputColumn():
     subprocess.call(['C:/R/GnuWin32/bin/awk.exe', '-F', '\",\"', 
              '\"{ print > (\\"split-\\" $10 \\".csv\\") }\"', 'large.csv'],
                  cwd = 'C:/R/GnuWin32/bin/')

很明显,当我执行函数(CPU 使用率等)时,有些东西正在运行,但是当我去检查 C:/R/GnuWin32/bin/ 时,目录中没有拆分文件。知道出了什么问题吗?

【问题讨论】:

  • 你有什么理由不用 Python 做同样的事情,所以你不必运行 awk?

标签: python python-3.x awk command-line


【解决方案1】:

正如我在之前被否决的回答中所说,您过度保护了参数,导致 awk 参数解析失败。

由于没有评论,我认为有一个错字,但它起作用了......所以我想这是因为我应该强烈建议一个成熟的 python 解决方案,这是最好的做法(如在我之前的回答)

在 python 中编写等价物并非易事,因为我们必须模拟 awk 打开文件并随后附加到文件的方式。但如果在输入文件中出现引用,它更加集成、pythonic 并且可以正确处理引用。

我花时间编写代码并对其进行测试:

def split_ByInputColumn():
    # get rid of the old data from previous runs
    for f in glob.glob("split-*.csv"):
        os.remove(f)

    open_files = dict()

    with open('large.csv') as f:
        cr = csv.reader(f,delimiter=',')
        for r in cr:
            tenth_row = r[9]
            filename = "split-{}.csv".format(tenth_row)
            if not filename in open_files:
                handle = open(filename,"wb")
                open_files[filename] = (handle,csv.writer(handle,delimiter=','))
            open_files[filename][1].writerow(r)

    for f,_ in open_files.values():
        f.close()

split_ByInputColumn()

详细说明:

  • 将大文件读取为csv(优点:引用处理得当)
  • 计算目标文件名
  • 如果文件名不在字典中,打开它并创建csv.writer对象
  • 在对应的字典中写入行
  • 最后,关闭文件句柄

旁白:我的旧解决方案,正确使用awk

import subprocess

def split_ByInputColumn():
     subprocess.call(['awk.exe', '-F', ',',
              '{ print > ("split-" $10 ".csv") }', 'large.csv'],cwd = 'some_directory')

【讨论】:

  • 感谢您重新回答并提供了一个很棒的 python 解决方案!
【解决方案2】:

其他人发布了一个答案(然后随后将其删除),但问题是我过度保护了我的论点。以下代码有效:

def split_ByInputColumn():
 subprocess.call(['C:/R/GnuWin32/bin/awk.exe', '-F', ',', 
          '{ print > (\"split-\" $10 \".csv\") }', 'large.csv'],
              cwd = 'C:/R/GnuWin32/bin/')

【讨论】:

  • 我的回答被否决了,所以我认为它不起作用,只是经过测试,它起作用了......
  • @Jean-FrançoisFabre 不确定您为什么被否决,但新答案更好 - 感谢您的帮助。
猜你喜欢
  • 2012-12-25
  • 2015-12-21
  • 1970-01-01
  • 2017-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
相关资源
最近更新 更多