从子进程调用的外部python脚本打印tqdm进度条

问题描述

我的主要目标是通过 subprocess 在另一个 python 脚本(调用者脚本)中运行外部 python 脚本(客户端脚本)。调用者脚本的控制台显示来自客户端脚本的所有输出 tqdm 输出除外 - 因此它不是通过 subprocess 显示输出的一般问题,而是与 {{ 1}} 与 subprocess 互动。

我的次要目标是我想了解它:)。非常感谢深思熟虑的解释。

客户端脚本 (train.py) 包含多个 tqdm 调用。到目前为止,我还没有看到各种 tqdm 参数配置之间的输出差异太大,所以让我们使用最简单的。

tqdm中:

train.py

调用者脚本 ... from tqdm import tqdm with tqdm(total = 10,ncols = 80,file=sys.stdout,position = 0,leave = True,desc='f5b: pbar.set_postfix') as pbar: for i in range(10): pbar.update(1) postfix = {'loss': '{0:.4f}'.format(1+i)} pbar.set_postfix(**postfix) sleep(0.1) 执行函数 experiment.py,该函数通过参数 execute_experiment 调用 train.py

command_list

此脚本调用上面的 train.py 代码片段确实返回输出,但 tqdm 输出在 0 秒后停止,如下所示:

def execute_experiment(command_list):
    tic = time.time()
    try:
        process = subprocess.Popen(
            command_list,shell=False,encoding='utf-8',bufsize=0,stdin=subprocess.DEVNULL,universal_newlines=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE
            )
        # Poll process for new output until finished
        # Source: https://stackoverflow.com/q/37401654/7769076
        while process.poll() is None:
            nextline = process.stdout.readline()
            sys.stdout.write(nextline)
            sys.stdout.flush()

    except CalledProcessError as err:
        print("CalledProcessError: {0}".format(err))
        sys.exit(1)

    except OSError as err:
        print("OS error: {0}".format(err))
        sys.exit(1)

    except:
        print("Unexpected error:",sys.exc_info()[0])
        raise

    if (process.returncode == 0):
        toc = time.time()
        time1 = str(round(toc - tic))
        return time1
    else:
        return 1

对train.py原始代码的脚本调用返回所有输出除了 tqdm输出

f5b: pbar.set_postfix:   0%|                             | 0/10 [00:00<?,?it/s]
f5b: pbar.set_postfix:  10%|█▊                | 1/10 [00:00<00:00,22310.13it/s]

评论

  1. Training default configuration train.py data --use-cuda ... device: cuda ... :作为python脚本调用python脚本。当 shell = False 时,根本不调用客户端脚本
  2. shell=True:防止缓冲
  3. bufsize=0 调用train.py 开头,以确保在本地机器上调用相应 conda 环境的 python 解释器。

问题:

  1. sys.executable 是否会阻止向上游传递进度条输出?我知道当调用 tqdm.set_postfix 时会发生这种情况,例如作者:

    pbar.set_description('已处理:%d' %(1 + i))

代码包含它:

tqdm.set_description
  1. 不显示进度条的原因是嵌套函数调用吗?

调用顺序为 def train(self,DataLoader,max_batches=500,verbose=True,**kwargs): with tqdm(total=max_batches,disable=not verbose,**kwargs) as pbar: for results in self.train_iter(DataLoader,max_batches=max_batches): pbar.update(1) postfix = {'loss': '{0:.4f}'.format(results['mean_outer_loss'])} if 'accuracies_after' in results: postfix['accuracy'] = '{0:.4f}'.format( np.mean(results['accuracies_after'])) pbar.set_postfix(**postfix) # for logging return results > experiment.py > train.py

nested.py 通过以下方式调用 train.py 中的 train 函数

对于范围内的纪元(args.num_epochs):

nested.py

尝试替代方案但未成功:

results_Metatraining = Metalearner.train(Meta_train_DataLoader,max_batches=args.num_batches,verbose=args.verbose,desc='Training',# leave=False
                  leave=True
                  ) 

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)