如何将我的 shell 扫描脚本嵌入到 Python 脚本中?

How do I embed my shell scanning-script into a Python script?

我一直在使用以下 shell 命令从名为 scanner_name 的扫描仪读取图像并将其保存在名为 file_name

的文件中
scanimage -d <scanner_name> --resolution=300 --format=tiff --mode=Color 2>&1 > <file_name>

这对我的目的来说效果很好。 我现在正试图将其嵌入到 python 脚本中。我需要的是像以前一样将扫描图像保存到文件中,并将任何标准输出(比如错误消息)捕获到字符串

我试过了

    scan_result = os.system('scanimage -d {} --resolution=300 --format=tiff --mode=Color 2>&1 > {} '.format(scanner, file_name))

但是当我 运行 在一个循环中(使用不同的扫描仪)时,扫描之间存在不合理的长时间滞后,并且直到下一次扫描开始时才会保存图像(文件创建为空文件,直到下一个扫描命令才被填充)。所有这些都带有 scan_result=0,即表示没有错误

有人向我推荐子流程方法运行(),我试过了

with open(file_name, 'w') as scanfile:

    input_params = '-d {} --resolution=300 --format=tiff --mode=Color 2>&1 > {} '.format(scanner, file_name)
    scan_result = subprocess.run(["scanimage", input_params], stdout=scanfile, shell=True)

但是这会以某种不可读的文件格式保存图像

关于可能出现的问题有什么想法吗?或者还有什么我可以尝试的,既可以保存文件又可以检查成功状态?

我怀疑问题是您正在打开输出文件,然后 运行在其中 subprocess.run()。这是没有必要的。最终结果是,您通过 Python 打开文件,然后让命令通过 OS 再次 打开文件 ,然后通过 OS 关闭文件Python。

JUST 运行 子进程,然后让 scanimage 2>&1> filename 命令创建文件(就像 运行 scanimage 直接在命令行。)

我认为 subprocess.check_output() 现在是捕获输出的首选方法。

from subprocess import check_output
# Command must be a list, with all parameters as separate list items
command = ['scanimage', 
           '-d{}'.format(scanner), 
           '--resolution=300', 
           '--format=tiff', 
           '--mode=Color', 
           '2>&1>{}'.format(file_name)]

scan_result = check_output(command)
print(scan_result)

但是,(runcheck_outputshell=True 是一个很大的安全风险......特别是如果 input_params 进入 [=36] =] 外部脚本。人们可以传递不需要的命令,并在 shell 中使用脚本的权限将它们 运行。

有时,shell=True 是 OS 命令正确 运行 所必需的,在这种情况下,最好的建议是使用实际的 Python 模块进行接口使用扫描仪 - 与让 Python 将 OS 命令传递给 OS 相比。

subprocess.run() 绝对比 os.system() 更受欢迎,但它们都不支持 运行 并行执行多个作业。您将需要使用 Python 的 multiprocessing 库之类的东西来并行 运行 多个任务(或者在基本的 subprocess.Popen() [=36= 之上自己痛苦地重新实现它) ]).

你对如何运行subprocess.run()也有一个基本的误解。您可以传入字符串和 shell=True 或标记列表和 shell=False(或者根本没有 shell 关键字;False 是默认值)。

with_shell = subprocess.run(
    "scanimage -d {} --resolution=300 --format=tiff --mode=Color 2>&1 > {} ".format(
        scanner, file_name), shell=True)

with open(file_name) as write_handle:
    no_shell = subprocess.run([
        "scanimage", "-d", scanner, "--resolution=300", "--format=tiff",
            "--mode=Color"],  stdout=write_handle)

您会注意到后者不支持重定向(因为这是一个 shell 功能),但这在 Python 中很容易实现。 (我去掉了标准错误的重定向——你真的希望错误消息保留在 stderr 上!)

如果您有一个更大的工作 Python 程序,那么与 multiprocessing.Pool() 集成应该不会很难。如果这是一个独立的小程序,我建议你完全剥离 Python 层并使用 xargs 或 GNU parallel 之类的东西来 运行 一个上限数量的并行子进程。