使用子进程自动重复执行计算密集型程序

发布于 2025-02-03 05:31:14 字数 1977 浏览 7 评论 0 原文

我想做的

我正在使用一个名为MESA的程序( https://docs.mesastar.org/en/latest/index.html )和每次运行的相关步骤是:

  1. 编辑几行,用文本文件中的输入参数
  2. 执行(bash)shell命令“ ./mk”
  3. 成功完成RN完成后,执行(bash)shell命令“ ./rn”

这些步骤将重复每次迭代。

我的实施

为了自动化这些步骤,我提出了以下程序:

import subprocess 

inputs[n][5] #2d array imported from csv

for i in range(len(inputs)):

    #read data
    with open('inlist', 'r', encoding='utf-8') as file:
            data = file.readlines()

    #lines to change
    data[ 73] = “   RSP_mass = ” + inputs[i][0] + “d0\n”
    data[ 74] = “   RSP_Teff = ” + inputs[i][1] + “d0\n”
    data[ 75] = “   RSP_L = ”+ inputs[i][2] + “d0\n”

    data[ 99] = “   log_directory = 'LOGS/” + inputs[i][3] + “'\n”
    data[100] = “   photo_directory = 'PHOTOS/” + inputs[i][4] + “'\n”

    #write data
    with open('inlist', 'r', encoding = 'utf-8') as file:
        file.writelines()

    #running MESA
    subprocess.run(“./mk”)
    subprocess.run(“./rn”, stdout = subprocess.PIPE)

第1期:

因为MESA在计算上非常密集(用尽了所有可用的16个线程)和我每次运行最多需要2½-3个小时,我非常担心可能的性能问题。由于每次运行时间长,因此也很难基准测试。

我错过了更好的解决方案吗?

第2期: 在运行期间,台面输出要小于1000行,我认为如果通过子过程运行,这将导致很慢。当然,最简单的方法就是禁用任何输出,但是能够在运行过程中检查演变过程非常有用,因此我想在可能的情况下保留它。从这个线程 python:python:读取subprocess'sprocess'sTdout而不打印到文件,我已经了解到stdout = subprocess.pipe是最快的方法。输出数据的存储已经由MESA本身处理。这是关于性能的好解决方案吗?

问题3: 这是问题中最不重要的,但是它可能会影响先前问题的实施,因此我想我也会询问这一点。是否可以定义自定义键盘中断,该中断不会立即终止程序,但只有在下一次运行完成后才终止程序?基于线程如何生成键盘事件?我会假设键盘库是最适合Ubuntu。

What I am trying to do

I am using a program called MESA (https://docs.mesastar.org/en/latest/index.html) and the relevant steps for each run are:

  1. Edit a few lines with input parameters in a text file
  2. Execute the (bash) shell command “./mk”
  3. Execute the (bash) shell command “./rn”

After successful completion of rn these steps are repeated for each iteration.

My implementation

In order to automate these steps I came up with the following program:

import subprocess 

inputs[n][5] #2d array imported from csv

for i in range(len(inputs)):

    #read data
    with open('inlist', 'r', encoding='utf-8') as file:
            data = file.readlines()

    #lines to change
    data[ 73] = “   RSP_mass = ” + inputs[i][0] + “d0\n”
    data[ 74] = “   RSP_Teff = ” + inputs[i][1] + “d0\n”
    data[ 75] = “   RSP_L = ”+ inputs[i][2] + “d0\n”

    data[ 99] = “   log_directory = 'LOGS/” + inputs[i][3] + “'\n”
    data[100] = “   photo_directory = 'PHOTOS/” + inputs[i][4] + “'\n”

    #write data
    with open('inlist', 'r', encoding = 'utf-8') as file:
        file.writelines()

    #running MESA
    subprocess.run(“./mk”)
    subprocess.run(“./rn”, stdout = subprocess.PIPE)

Issue 1:

Since MESA is very computationally intensive (uses up all of the available 16 threads) and already takes up to 2 ½ - 3 hours per run, I am quite worried about possible performance issues. Due to the long run time per run, its also quite difficult to benchmark.

Is there a better solution available, that I have missed?

Issue 2:
During a run MESA outputs a little less than 1000 lines to stdout, which I assume will cause quite a slow down if running via subprocess. The easiest way would be of course to just disable any output, however it is quite useful to be able to check the evolution process during runs, so I would like to keep it if possible. From this thread
Python: Reading a subprocess' stdout without printing to a file, I have already learned that stdout=subprocess.PIPE would be the fastest way of doing so. The storing of the output data is already handled by MESA itself. Is this a good solution in regards to performance?

Issue 3:
This is the least important of the issues, however it might affect the implementation of the prior issues, so I thought I would ask about it as well. Is it possible to define a custom keyboard interrupt, which doesn’t terminate the program immediately, but only once the next run has completed? Based on the thread How to generate keyboard events? I would assume the keyboard library would be best suited for Ubuntu.

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

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

发布评论

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

评论(1

回忆凄美了谁 2025-02-10 05:31:14

反复读取和重写输入文件是笨拙且效率低下的,无论如何,当您以读取模式打开时,您无法写入它('r')。

相反,我会读取一个模板文件,然后根据该文件编写实际的配置文件。 (python有一个单独的也许值得研究,但这足够简单,可以从头开始写

。来自Python。

如果您没有理由从过程中捕获输出,请直接溢出到用户的终端上。在 subprocess 中,请未为 stdout = stdout = stderr = 指定任何内容。

import subprocess 

# inputs[n][5] #2d array imported from csv

with open('template', 'r', encoding='utf-8') as file:
    data = file.readlines()

for inp in inputs:
    data[ 73] = f"   RSP_mass = {inp[0]}d0\n"
    data[ 74] = f"   RSP_Teff = {inp[1]}d0\n"
    data[ 75] = f"   RSP_L = {inp[2]}d0\n"

    data[ 99] = f"   log_directory = 'LOGS/{inp[3]}'\n"
    data[100] = f"   photo_directory = 'PHOTOS/{inp[4]}'\n"

    with open('inlist', 'w', encoding = 'utf-8') as file:
        file.writelines()

    subprocess.run("./mk", check=True)
    subprocess.run("./rn", check=True)

请注意,现在如何从 template 的文件中读取此内容,然后将其写入('w' inlist 。我还将循环修复了一些惯用性,并将卷曲的双引号更改为适当的ASCII双引号。现在,替代品使用(IMHO)提高的可透性。在末尾, check = true 关键字参数to subprocess.run 指示如果子过程失败,请python提出错误。

键盘中断的想法听起来不必要地具有挑战性。您可以添加信号处理程序以选择性地忽略某些信号,但是一个简单的解决方案就是检查是否在循环中按下是否有任何常规密钥(或特定的密钥;例如 Q )。请参阅Eg 如何检测按键按下?

Repeatedly reading and rewriting the input file is clumsy and inefficient, and anyway, you can't write to it when you open it in read-only mode ('r').

I would instead read a template file, once, then write the actual configuration file based on that. (Python has a separate Template class in the standard library which would perhaps be worth looking into, but this is simple enough to write from scratch.)

A subprocess simply leaves Python completely out of the picture, so running your tasks from the shell should work the same as running them from Python.

If you have no reason to capture the output from the process, just let it spill onto the user's terminal directly. Not specifying anything for stdout= and stderr= in the subprocess call achieves that.

import subprocess 

# inputs[n][5] #2d array imported from csv

with open('template', 'r', encoding='utf-8') as file:
    data = file.readlines()

for inp in inputs:
    data[ 73] = f"   RSP_mass = {inp[0]}d0\n"
    data[ 74] = f"   RSP_Teff = {inp[1]}d0\n"
    data[ 75] = f"   RSP_L = {inp[2]}d0\n"

    data[ 99] = f"   log_directory = 'LOGS/{inp[3]}'\n"
    data[100] = f"   photo_directory = 'PHOTOS/{inp[4]}'\n"

    with open('inlist', 'w', encoding = 'utf-8') as file:
        file.writelines()

    subprocess.run("./mk", check=True)
    subprocess.run("./rn", check=True)

Notice how this now reads from a file called template, once outside the loop, and then writes ('w') to inlist repeatedly. I also fixed the loop to be a bit more idiomatic, and changed the curly double quotes to proper ASCII double quotes. The replacements now use f-strings for (IMHO) improved legibility. Down near the end, the check=True keyword argument to subprocess.run instructs Python to raise an error if the subprocess fails.

The keyboard interrupt idea sounds unnecessarily challenging. You can add a signal handler to selectively ignore some signals, but a much simpler solution would be to just check whether any regular key (or a specific one; say q) has been pressed within the loop. See e.g. How to detect key presses?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文