【问题标题】:Python subprocess column invalid option [duplicate]Python子进程列无效选项[重复]
【发布时间】:2026-01-24 13:45:02
【问题描述】:

我想要求 shell 在我的 python 脚本中以一种很好的格式显示一个csv 文件。所以我写了以下内容:

printout = "column -s, -t < output.csv | less -#2 -N -S "
subprocess.call(printout.split(), shell = False)

我得到的错误是:

column: invalid option -- '#'

我有一个粗略的想法,它与shell=False有关;但是,当我将其设置为 True 并在 cmd 行中运行时,它会将我置于另一行,我必须 ctrl+C 才能退出。

【问题讨论】:

  • shell=False 表示您没有外壳,因此没有任何东西知道如何处理重定向 (&lt;) 或管道 (|)。使用shell=False 实际上更好,但这意味着您需要在 Python 中进行更多设置。

标签: python command-line subprocess


【解决方案1】:

您的原始代码等同于 shell 命令:

# this can be used to reproduce your bug at a shell
column -s, -t '<' output.csv '|' less -#2 -N -S

...将&lt;|less 等作为column 的参数传递,而不是将它们视为shell 指令。


请参阅subprocess 模块文档中的Replacing Shell Pipelines 部分。

p1 = subprocess.Popen(['column', '-s,', '-t'],
                      stdin=open('output.csv', 'r'),
                      stdout=subprocess.PIPE)
p2 = subprocess.Popen(['less', '-#2', '-N', '-S'],
                      stdin=p1.stdout)
p1.stdout.close() # ensure that p2 has the only remaining handle on p1.stdout
p2.communicate()  # let less run

【讨论】:

  • 为什么我们需要像'column','-s,'这样的单独列表条目......我们可以像'column -s -t'那样使用它吗?或者前一种方法的优势是什么
  • @pankajmishra,这种方法的优点是您不依赖外壳为您进行拆分。这是更好的做法,因为像split() 甚至shlex.split() 这样的东西可能会被意外或恶意文件名故意误导或破坏——想想如果你的output.csv 来自变量并且文件名有空格会发生什么在里面。
  • 天啊!谢谢SOOOOOO MUUUCH
  • @pankajmishra, ...有些人会有些天真地使用 "'%s'" % filenameshlex.split()shell=True 之类的引用,但如果文件名包含文字 's,即使这样也不起作用然后可以逃脱句法的。
  • @pankajmishra, ...另一点是字符串列表实际上是操作系统级别的 argv 列表的本机格式——在 UNIX 上启动其他程序的方式是execve 系统调用,它需要一个 C 字符串列表。您对 single 字符串而不是列表所做的任何事情都需要在实际使用之前分解/转换为该列表;自己传递一个列表意味着你拥有绝对的控制权,而不是依赖于任何转换来按照你想要的方式去做。