如何将我的 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)
但是,(run
和 check_output
)shell=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
之类的东西来 运行 一个上限数量的并行子进程。
我一直在使用以下 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)
但是,(run
和 check_output
)shell=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
之类的东西来 运行 一个上限数量的并行子进程。