0

对于我的程序,我有一个将随机整数写入 .CSV 文件的文件。

from __future__ import absolute_import, division, print_function
from numpy.random import randint as randrange
import os, argparse, time
from tqdm import tqdm

def write_to_csv(filename, *args, newline = True):
    write_string = ''
    for arg in args:
        if type(arg) == list:
            for i in arg:
                write_string += str(i) + ','
        else:
            write_string += str(arg) + ','
    if newline:
        write_string = write_string.rstrip(',') + '\n'
    else:
        write_string = write_string.rstrip(',')
    with open(filename+'.csv', 'a') as file:
        file.write(write_string)

def move_dir(dirname, parent = False):
    if not parent:
        dirname = str(dirname)
        exists = os.path.isfile(dirname)
        try:
            os.mkdir(dirname)
            os.chdir(dirname)
        except FileExistsError:
            os.chdir(dirname)
    else:
        os.chdir("..")

def calculate_probability(odds, exitmode = False, low_cpu = 0):
    try:
        file_count = 0
        move_dir('Probability')
        move_dir(str(odds))
        d = {}
        writelist = []
        percentlist = []
        for i in tqdm(range(odds)):
            d[str(i)] = 0
            writelist.append(f'Times {i}')
            percentlist.append(f'Percent {i}')
        while True:
            if os.path.isfile(str(file_count)+'.csv'):
                file_count += 1
            else:
                break
        filename = str(file_count)
        write_to_csv(filename, 'Number', 'Value')
        rep = 500 * odds
        if rep > 10000:
            rep = 10000
        for i in tqdm(range(rep)):
            ran = randrange(odds)
            ran = int(ran)
            d[str(ran)] += 1
            if i == 999:
                write_to_csv(filename, i, ran+1, newline = False)
            else:
                write_to_csv(filename, i, ran+1)
            if low_cpu:
                time.sleep(0.01*float(low_cpu))
        writelist2 = []
        percentlist2 = []
        for i in tqdm(range(odds)):
            val = d[str(i)]
            writelist2.append(val)
            percentlist2.append(round(((val/rep)*100), 2))
        if os.path.isfile('runs.csv'):
            write_to_csv('runs', file_count, writelist2, percentlist2)
        else:
            write_to_csv('runs', 'Run #', writelist, percentlist)
            write_to_csv('runs', file_count, writelist2, percentlist2)
        if exitmode:
            exit()
    except(KeyboardInterrupt, SystemExit):
        if exitmode:
            os.remove(str(file_count)+'.csv')
            exit()
        else:
            try:
                os.system('cls')
                print('User/program interrupted, lauching shutdown mode...')
                os.remove(str(file_count)+'.csv')
                print('Finilizaing current trial...')
                os.chdir("..")
                os.chdir("..")
            except FileNotFoundError:
                exit()
            calculate_probability(odds, exitmode = True)

我也有一个重复系统可以多次执行此操作。

def run_tests(times, odds, low_cpu = 0, shutdown = False):
    for i in tqdm(range(times)):
        calculate_probability(odds, low_cpu = low_cpu)
        os.chdir("..")
        os.chdir("..")
    if shutdown:
        os.system('shutdown /S /F /T 0 /hybrid')

但是,如果我要跑 30 条小径,那将需要很长时间。所以我决定使用多处理模块来加速这个过程。因为每次运行最后都需要写入同一个文件,所以我不得不在进程结束后收集数据并写入它们。

def calculate_probability(odds, low_cpu = 0):
    try:
        file_count = 0
        move_dir('Probability')
        move_dir(str(odds))
        d = {}
        writelist = []
        percentlist = []
        for i in tqdm(range(odds)):
            d[str(i)] = 0
            writelist.append(f'Times {i}')
            percentlist.append(f'Percent {i}')
        while True:
            if os.path.isfile(str(file_count)+'.csv'):
                file_count += 1
            else:
                break
        filename = str(file_count)
        write_to_csv(filename, 'Number', 'Value')
        rep = 500 * odds
        if rep > 10000:
            rep = 10000
        for i in range(rep):
            ran = randrange(odds)
            ran = int(ran)
            d[str(ran)] += 1
            if i == 999:
                write_to_csv(filename, i, ran+1, newline = False)
            else:
                write_to_csv(filename, i, ran+1)
            if low_cpu:
                time.sleep(0.01*float(low_cpu))
        writelist2 = []
        percentlist2 = []
        for i in range(odds):
            val = d[str(i)]
            writelist2.append(val)
            percentlist2.append(round(((val/rep)*100), 2))
        return (writelist, percentlist, writelist2, percentlist2)
    except(KeyboardInterrupt, SystemExit):
        try:
            os.remove(str(file_count)+'.csv')
        finally:
            exit()

def worker(odds, returndict, num, low_cpu = 0):
    returndict[f'write{num}'] = calculate_probability(odds, low_cpu = low_cpu)
    os.chdir("..")
    os.chdir("..")
    os.system('cls')

def run_tests(times, odds, low_cpu = 0, shutdown = False):
    print('Starting...')
    manager = Manager()
    return_dict = manager.dict()
    job_list = []
    for i in range(times):
        p = Process(target=worker, args=(odds,return_dict,i), kwargs = {'low_cpu' : low_cpu})
        job_list.append(p)
        p.start()

    try:
        for proc in job_list:
            proc.join()
    except KeyboardInterrupt:
        print('User quit program...')
        time.sleep(5)
        for proc in job_list:
            proc.join()
        exit()
    else:
        move_dir('Probability')
        move_dir(str(odds))
        if not os.path.isfile('runs.csv'):
            write_to_csv('runs', return_dict.values()[0][0], return_dict.values()[0][1])
        for value in return_dict.values():
            write_to_csv('runs', value[2], value[3])
        print('Done!')
    finally:
        if shutdown:
            os.system('shutdown /S /F /T 0 /hybrid')

但是,当我运行这个新代码时,有一个进度条,每个进程都会覆盖进度条,所以进度条闪烁着随机数,使进度条很有用。我想有一堆栏,每个进程一个,每次更新都不会中断其他进程。条形不需要订购;我只需要了解每个进程执行任务的速度。

4

1 回答 1

0

STDOUT 只是一个流,您的所有进程都附加到同一个流,因此没有直接的方法可以告诉它在不同的行上打印来自不同进程的输出。

实现这一点的最简单方法可能是拥有一个单独的流程,负责汇总所有其他流程的状态并报告结果。您可以使用 multiprocessing.Queue 将数据从工作线程传递到状态线程,然后状态线程可以将状态打印到标准输出。如果您想要一堆进度条,则必须在格式方面获得一些创意(基本上同时更新所有进度条并以相同的顺序打印它们,以便它们看起来堆叠起来)。

于 2018-02-03T23:04:55.287 回答