使用python进行进度测量';s多处理池和映射函数
我正在使用以下代码进行并行csv处理:使用python进行进度测量';s多处理池和映射函数,python,multithreading,csv,parallel-processing,python-multiprocessing,Python,Multithreading,Csv,Parallel Processing,Python Multiprocessing,我正在使用以下代码进行并行csv处理: #!/usr/bin/env python import csv from time import sleep from multiprocessing import Pool from multiprocessing import cpu_count from multiprocessing import current_process from pprint import pprint as pp def init_worker(x): sle
#!/usr/bin/env python
import csv
from time import sleep
from multiprocessing import Pool
from multiprocessing import cpu_count
from multiprocessing import current_process
from pprint import pprint as pp
def init_worker(x):
sleep(.5)
print "(%s,%s)" % (x[0],x[1])
x.append(int(x[0])**2)
return x
def parallel_csv_processing(inputFile, outputFile, header=["Default", "header", "please", "change"], separator=",", skipRows = 0, cpuCount = 1):
# OPEN FH FOR READING INPUT FILE
inputFH = open(inputFile, "rt")
csvReader = csv.reader(inputFH, delimiter=separator)
# SKIP HEADERS
for skip in xrange(skipRows):
csvReader.next()
# PARALLELIZE COMPUTING INTENSIVE OPERATIONS - CALL FUNCTION HERE
try:
p = Pool(processes = cpuCount)
results = p.map(init_worker, csvReader, chunksize = 10)
p.close()
p.join()
except KeyboardInterrupt:
p.close()
p.join()
p.terminate()
# CLOSE FH FOR READING INPUT
inputFH.close()
# OPEN FH FOR WRITING OUTPUT FILE
outputFH = open(outputFile, "wt")
csvWriter = csv.writer(outputFH, lineterminator='\n')
# WRITE HEADER TO OUTPUT FILE
csvWriter.writerow(header)
# WRITE RESULTS TO OUTPUT FILE
[csvWriter.writerow(row) for row in results]
# CLOSE FH FOR WRITING OUTPUT
outputFH.close()
print pp(results)
# print len(results)
def main():
inputFile = "input.csv"
outputFile = "output.csv"
parallel_csv_processing(inputFile, outputFile, cpuCount = cpu_count())
if __name__ == '__main__':
main()
我想以某种方式衡量脚本的进度(只是纯文本,而不是任何花哨的ASCII艺术)。我想到的一个选项是将init_worker
成功处理的行与input.csv中的所有行进行比较,并打印实际状态,例如每秒打印一次,您能告诉我正确的解决方案吗?我发现有几篇文章有类似的问题,但我无法将其适应我的需要,因为它们都没有使用Pool
类和map
方法。我还想问一下p.close()、p.join()、p.terminate()
方法,我主要在Process
而不是Pool
类中见过它们,它们是Pool
类所必需的吗?我是否正确使用了它们?使用p.terminate()
是为了用ctrl+c终止进程,但这个故事还没有圆满结束。多谢各位
PS:My input.csv看起来像这样,如果重要的话:
0,0
1,3
2,6
3,9
...
...
48,144
49,147
PPS:正如我所说,我是多处理方面的新手,我编写的代码很有效。我看到的一个缺点是整个csv都存储在内存中,所以如果你们有更好的想法,请毫不犹豫地分享它
编辑
回复@J.F.Sebastian
以下是我根据您的建议编写的实际代码:
#!/usr/bin/env python
import csv
from time import sleep
from multiprocessing import Pool
from multiprocessing import cpu_count
from multiprocessing import current_process
from pprint import pprint as pp
from tqdm import tqdm
def do_job(x):
sleep(.5)
# print "(%s,%s)" % (x[0],x[1])
x.append(int(x[0])**2)
return x
def parallel_csv_processing(inputFile, outputFile, header=["Default", "header", "please", "change"], separator=",", skipRows = 0, cpuCount = 1):
# OPEN FH FOR READING INPUT FILE
inputFH = open(inputFile, "rb")
csvReader = csv.reader(inputFH, delimiter=separator)
# SKIP HEADERS
for skip in xrange(skipRows):
csvReader.next()
# OPEN FH FOR WRITING OUTPUT FILE
outputFH = open(outputFile, "wt")
csvWriter = csv.writer(outputFH, lineterminator='\n')
# WRITE HEADER TO OUTPUT FILE
csvWriter.writerow(header)
# PARALLELIZE COMPUTING INTENSIVE OPERATIONS - CALL FUNCTION HERE
try:
p = Pool(processes = cpuCount)
# results = p.map(do_job, csvReader, chunksize = 10)
for result in tqdm(p.imap_unordered(do_job, csvReader, chunksize=10)):
csvWriter.writerow(result)
p.close()
p.join()
except KeyboardInterrupt:
p.close()
p.join()
# CLOSE FH FOR READING INPUT
inputFH.close()
# CLOSE FH FOR WRITING OUTPUT
outputFH.close()
print pp(result)
# print len(result)
def main():
inputFile = "input.csv"
outputFile = "output.csv"
parallel_csv_processing(inputFile, outputFile, cpuCount = cpu_count())
if __name__ == '__main__':
main()
下面是TQM的输出:
1 [elapsed: 00:05, 0.20 iters/sec]
这个输出意味着什么?在您提到的页面上,tqdm
以以下方式循环使用:
>>> import time
>>> from tqdm import tqdm
>>> for i in tqdm(range(100)):
... time.sleep(1)
...
|###-------| 35/100 35% [elapsed: 00:35 left: 01:05, 1.00 iters/sec]
这个输出是有意义的,但是我的输出意味着什么?而且,似乎ctrl+c问题并没有得到解决:在点击ctrl+c后,脚本会抛出一些回溯,若我再次点击ctrl+c,那个么我会得到新的回溯,以此类推。杀死它的唯一方法是将它发送到后台(ctr+z),然后杀死它(杀死%1)要显示进度,请将
pool.map
替换为pool.imap\u无序
:
from tqdm import tqdm # $ pip install tqdm
for result in tqdm(pool.imap_unordered(init_worker, csvReader, chunksize=10)):
csvWriter.writerow(result)
零件是可选的,请参见
意外地,它修复了“整个csv存储在内存中”和“键盘中断未引发”问题
下面是一个完整的代码示例:
#!/usr/bin/env python
import itertools
import logging
import multiprocessing
import time
def compute(i):
time.sleep(.5)
return i**2
if __name__ == "__main__":
logging.basicConfig(format="%(asctime)-15s %(levelname)s %(message)s",
datefmt="%F %T", level=logging.DEBUG)
pool = multiprocessing.Pool()
try:
for square in pool.imap_unordered(compute, itertools.count(), chunksize=10):
logging.debug(square) # report progress by printing the result
except KeyboardInterrupt:
logging.warning("got Ctrl+C")
finally:
pool.terminate()
pool.join()
您应该每
.5*chunksize
秒查看一次批输出。如果按Ctrl+C组合键;您应该看到在子进程和主进程中引发的KeyboardInterrupt
。在Python3中,主进程立即退出。在Python2中,KeyboardInterrupt
被延迟,直到下一批应该打印出来为止(Python中的bug)。无关:在Python2上对csv文件使用'rb'
模式。此外,初始化工作人员
名称具有误导性init_worker
在您的情况下可能在同一个worker进程中运行多次。无关:在p.join()
之后调用p.terminate()
是毫无意义的。不幸的是,这似乎没有帮助,请检查编辑的OP。非常感谢。@WakanTanka:(1)如果您不理解TQM的输出,那么只需放下它,在每次迭代中以您喜欢的方式打印进度报告即可。(2)在异常处理程序中使用p.terminate()
。把它放在join()之前。Hi@J.F.塞巴斯蒂安很抱歉稍后再回复。我了解TQM的输出,但问题是它是按进程报告的,而不是针对整个任务。PS:除了键盘中断:分支外,我在中的p.terminate()
和p.join()
之间放置了p.close()
,按下ctrl+c
后,我仍然会得到相同的行为。你能不能把整个代码都贴出来,这样我就可以接受答案了。非常感谢。