我如何在Python中命名一个外部命令,就好像我把它写在一个<unk>或命令中?


当前回答

在Python 3.5+中使用子过程,以下是我在Linux上做的技巧:

import subprocess

# subprocess.run() returns a completed process object that can be inspected
c = subprocess.run(["ls", "-ltrh"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(c.stdout.decode('utf-8'))

正如文档中提到的那样,PIPE 值是比特序列,为了正确显示它们,应考虑解码。

上述代码的结果是:

total 113M
-rwxr-xr-x  1 farzad farzad  307 Jan 15  2018 vpnscript
-rwxrwxr-x  1 farzad farzad  204 Jan 15  2018 ex
drwxrwxr-x  4 farzad farzad 4.0K Jan 22  2018 scripts
.... # Some other lines

其他回答

使用 subprocess.call:

from subprocess import call

# Using list
call(["echo", "Hello", "world"])

# Single string argument varies across platforms so better split it
call("echo Hello world".split(" "))

最多案例:

在大多数情况下,一个短片的代码,如此,是你将需要的一切:

import subprocess
import shlex

source = "test.txt"
destination = "test_copy.txt"

base = "cp {source} {destination}'"
cmd = base.format(source=source, destination=destination)
subprocess.check_call(shlex.split(cmd))

它是干净和简单的。

subprocess.check_call 以论点运行命令,等待命令完成。 shlex.split 使用 shell-like syntax 分割行 cmd

其他案例:

如果这不适用于某些特定的命令,最有可能你有一个问题与命令线的解释器. 操作系统选择了默认一个不适合你的程序类型或可能没有找到适当的一个在系统可执行的路径。

例子:

使用Unix系统上的转向操作器

input_1 = "input_1.txt"
input_2 = "input_2.txt"
output = "merged.txt"
base_command = "/bin/bash -c 'cat {input} >> {output}'"

base_command.format(input_1, output=output)
subprocess.check_call(shlex.split(base_command))

base_command.format(input_2, output=output)
subprocess.check_call(shlex.split(base_command))

正如《Python Zen: Explicit is better than implicit》中所说的那样。

因此,如果使用 Python >=3.6 函数,它会看起来像这样:

import subprocess
import shlex

def run_command(cmd_interpreter: str, command: str) -> None:
    base_command = f"{cmd_interpreter} -c '{command}'"
    subprocess.check_call(shlex.split(base_command)

如果您在命令中不使用用户输入,您可以使用以下操作:

from os import getcwd
from subprocess import check_output
from shlex import quote

def sh(command):
    return check_output(quote(command), shell=True, cwd=getcwd(), universal_newlines=True).strip()

用它作为

branch = sh('git rev-parse --abbrev-ref HEAD')

shell=True 将扫描一个阴道,所以你可以使用管道和这样的阴道事物 sh('ps auxibh grep python'). 这是非常方便的运行硬编码命令和处理其输出。

但这不是安全的用户输入,从文档:

安全考虑 与其他某些字符功能不同,此实施将永远不会随意称为系统字符,这意味着所有字符,包括字符字符字符,都可以安全地转移到儿童过程,如果字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符字符

In [50]: timeit("check_output('ls -l'.split(), universal_newlines=True)", number=1000, globals=globals())
Out[50]: 2.6801227919995654

In [51]: timeit("check_output('ls -l', universal_newlines=True, shell=True)", number=1000, globals=globals())
Out[51]: 3.243950183999914

这里还有另一个区别,以前没有提到。

subprocess.Popen 执行 <命令> 作为一个子过程. 在我的情况下,我需要执行与另一个程序, <b> 沟通的 <a> 文件。

我尝试了子过程,执行成功了,但是 <b> 无法与 <a> 沟通,当我从终端运行时,一切都正常。

另外一个: (注意: kwrite 与其他应用程序不同,如果您尝试下面的 Firefox,结果将不相同。

如果你尝试 os.system(“kwrite”),程序流冻结,直到用户关闭 kwrite. 为了克服我尝试了 os.system(控制台 -e kwrite)。 这次程序继续流动,但 kwrite 成为控制台的子过程。

任何人运行基里特不是一个子过程(即在系统监控器中,它必须出现在树的左边)。

假设你想从一个 CGI 脚本开始一个漫长的任务,也就是说,孩子的过程应该比 CGI 脚本执行过程更长。

从子过程模块文档的经典例子是:

import subprocess
import sys

# Some code here

pid = subprocess.Popen([sys.executable, "longtask.py"]) # Call subprocess

# Some more code here

我的目标平台是FreeBSD,但开发是在Windows上,所以我首先面对了Windows上的问题。

在Windows(Windows XP)上,父母过程不会完成,直到 longtask.py 完成了工作。 这不是你想要的 CGI 脚本. 问题不是具体的 Python; 在 PHP 社区,问题是相同的。

解决方案是将 DETACHED_PROCESS Process Creation Flag 转移到 Windows API 中的 CreateProcess 功能。 如果您安装了 pywin32,您可以从 win32 过程模块中导入旗帜,否则您应该自己定义:

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid

pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

我没有在其他平台上检查代码,也不知道FreeBSD的行为原因,如果有人知道的话,请分享你的想法。