繁体   English   中英

有没有办法检查脚本是否从子进程运行?

[英]Is there a way to check if script is running from subprocess?

假设我有一个 python 脚本,它读取文件夹中的所有图像并调整它们的大小。 该脚本完全由他自己运行,它接受两个参数 - 输入文件夹和输出文件夹。 为了获得进度的视觉响应,我使用了一个打印到控制台/终端的进度条。

调整大小.py:

import argparse
import fnmatch
import os
import PIL
from PIL import Image
from progress.bar import Bar

parser = argparse.ArgumentParser(description='Photo resizer.')
parser.add_argument('input_folder', nargs='?', default='', help="Input folder")
parser.add_argument('export_folder', nargs='?', default='', help="Output folder")
args = parser.parse_args()

if args.input_folder:
    input_folder = args.input_folder
if args.export_folder:
    export_resized_folder = args.export_folder

NEW_SIZE = 2000

inputFiles = []
for root, dirnames, filenames in os.walk(input_folder):
    for filename in fnmatch.filter(filenames, '*.jpg'):
        inputFiles.append(os.path.join(root, filename))

bar = Bar("Processing photos", max=len(inputFiles), check_tty=False)
for photo in inputFiles:
    filename = os.path.basename(photo)
    im = Image.open(photo)
    im_width, im_height = im.size
    if im_width > im_height:
        new_width = NEW_SIZE
        new_height = int(NEW_SIZE * im_height / im_width)
    else:
        new_height = NEW_SIZE
        new_width = int(NEW_SIZE * im_width / im_height)
    new_size = (new_width, new_height)
    im_resized = im.resize(new_size, resample=PIL.Image.Resampling.LANCZOS)
    im_resized.save(os.path.join(export_resized_folder, filename), quality=70)
    bar.next()
bar.finish()

现在我有另一个脚本(main_gui.py),它进行一些批处理,其中一项工作是调整图像大小。 该脚本提供了一个简单的 GUI。 在调整图像大小时,我使用subprocess Popen执行脚本并将输入和输出文件夹作为 args 传递。

所以在main_gui.py我启动子进程:

script_path = "resize.py"
process = subprocess.Popen(["python", script_path, INPUT_FOLDER, OUTPUT_FOLDER], universal_newlines=True, stdout=subprocess.PIPE)

现在我也想看看 GUI 的进展。 我不知道我是否做对了(很有可能不是,这只是我想到的第一件事)......
因此,在resize.py和进度条中,我打印出有关我的进度的信息,然后在main_gui.py中读取它,并根据该信息更新 tkinter 进度条。

resize.py中:

bar = Bar("Processing photos", max=len(inputFiles), check_tty=False)
print("**TOTAL** " + str(len(inputFiles)))
...
progressCounter = 1
for photo in inputFiles:
   ...
   bar.next()
   print("**PROGRESS** " + str(progressCounter)) 
   progressCounter += 1
   ...

我在main_gui.py中阅读了这些值

process = subprocess.Popen(["python", script_path], universal_newlines=True, stdout=subprocess.PIPE)

while process.poll() is None:
    data = process.stdout.readline().strip()
    print(data)
    if "**TOTAL** " in data:
        total = int(data.replace("**TOTAL** ", ""))
        progressbarWidget['maximum'] = total
    if "**PROGRESS** " in data and self.GUI:
        progressCounter = int(data.replace("**PROGRESS** ", ""))
        progressbarWidget['value'] = progressCounter
        progressbarWidget.update_idletasks()

在这一点上,我想在我的resize.py中检查它是由自己运行还是由子进程运行,所以我没有不必要的打印语句。

正如查尔斯在评论中建议的那样,我尝试传入一个 env 值,但无法完成

对于这个用例来说,试图检测你的父进程是不必要的魔法。 使用可选参数使其显式化将使其他人编写自己的 GUI(可能使用非 Python 语言)获得机器可读的状态输出,而无需尝试欺骗检测。

parser = argparse.ArgumentParser(description='Photo resizer.')
parser.add_argument('--progress', choices=('none', 'human', 'machine-readable'), default='none',
                    help="Should a progress bar be written to stderr in a human-readable form, to stdout in a machine-readable form, or not at all?")
parser.add_argument('input_folder', nargs='?', default='', help="Input folder")
parser.add_argument('export_folder', nargs='?', default='', help="Output folder")
args = parser.parse_args()

……然后后来……

if args.progress == 'machine-readable':
  pass # TODO: Write your progress messages for the programmatic consumer to stdout here
elif args.progress == 'human':
  pass # TODO: Write your progress bar for a human reader to stderr here

在 GUI 端,将--progress=human添加到参数列表中:

process = subprocess.Popen([sys.executable, script_path, '--progress=human'],
                           universal_newlines=True, stdout=subprocess.PIPE)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM