有没有办法检查脚本是否正在从子过程中运行?

发布于 2025-02-07 08:40:10 字数 3065 浏览 0 评论 0原文

假设我有一个python脚本,该脚本在文件夹中读取所有图像并调整它们。该脚本全部运行,它需要两个参数 - 输入文件夹和一个输出文件夹。 要对进度的目视响应,我使用的是一个进度键,该进度键将其打印到控制台/终端。

resize.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执行脚本并将输入文件夹传递到ARG中。

因此,在 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.py 和progressbar中,我打印出有关进度的信息,然后在 main_gui.py.py 中读取它,并基于该信息,我更新了tkinter progressbar。

resize.py.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.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()

值是由本身或子过程运行的,因此我没有不必要的打印语句。

我尝试按照查尔斯在评论中的建议中传递一个env价值,但无法完成

Let's say I have a python script which reads all the images in a folder and resizes them. The script works all by his own, it takes in two arguments - the input folder and an output folder.
To have a visual response of the progress I'm using a progressbar which is printed out to the console/terminal.

resize.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()

Now I have an another script (main_gui.py) which does some batch processing and one of the jobs is to resize the images. This script provides a simple GUI. When it comes to resizing the images, I use subprocess Popen to execute the script and pass in the input and output folders as args.

So in main_gui.py I start the subprocess:

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

Now I'd like to see the progress in the GUI also. I don't know if I'm doing it correctly (It is a high probability that not, this is just the first thing that came to my mind)...
So in resize.py along with the progressbar I print out information about my progress and then read it in the main_gui.py and based on that information I update a tkinter progressbar.

In 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
   ...

I read these values in 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()

And at this point I'd like in my resize.py check if it is run by itself or by the subprocess, so I don't have the unnecessary print statements.

I tried pass in an env value as Charles suggested in the comments, but couldn't get it done

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

把人绕傻吧 2025-02-14 08:40:10

试图检测您的父进程对于此用例来说是不必要的魔术。用可选的参数明确说明它将让其他人编写自己的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)

Trying to detect your parent process is an unnecessary amount of magic for this use case. Making it explicit with an optional argument will let others writing their own GUIs (potentially in non-Python languages) get the machine-readable status output without needing to try to fool the detection.

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()

...and then later...

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

while on the GUI side, adding --progress=human to the argument list:

process = subprocess.Popen([sys.executable, script_path, '--progress=human'],
                           universal_newlines=True, stdout=subprocess.PIPE)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文