免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3523 | 回复: 2
打印 上一主题 下一主题

perl下多进程的进度显示 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-10-07 16:05 |只看该作者 |倒序浏览
经常遇到这样的需求, 一个父进程开启多个子进程, 每个子进程都需要做一个长时间的处理, 所以希望显示这些子进程的进度. 在网上可以找到单进程的进度显示, 但多进程的进度显示没找着.  
所以就自己想着做一个, 希望大家给点意见,要是有更好的方法的话请分享一下.


  1. #!/usr/local/bin/perl5

  2. use warnings;
  3. use strict;
  4. use Fcntl;
  5. use Term::Cap;
  6. use Parallel::ForkManager;

  7. #==============================
  8. # for terminal control
  9. #==============================
  10. my $termios = new POSIX::Termios;
  11. my $terminal = Term::Cap->Tgetent ({ TERM => undef, OSPEED => $termios->getospeed });
  12. $terminal->Trequire(qw(cm sc rc)); #check if terminal support these capabilities
  13. my $c = `clear`;
  14. print $c;

  15. #==============================
  16. # for fifo
  17. #==============================
  18. my $fpath = "myfifo";
  19. unless (-p $fpath) {
  20.     if (-e _) {
  21.         die "$fpath is something unknow\n";
  22.     }
  23.     else {
  24.         require POSIX;
  25.         POSIX::mkfifo($fpath, 0666) or die "can not mknod $fpath: $!";
  26.         print "$0: created $fpath as a named pipe\n";
  27.     }
  28. }
  29. else {
  30.     print "$0: named pipe $fpath exists\n";
  31. }


  32. #==============================
  33. # for parallel processes
  34. #==============================
  35. my @names;
  36. push @names, "p$_" foreach 0..5;
  37. my $childs;
  38. $childs->{$_} = {total=>1, processed=>0, name => $names[$_]} foreach(0.. $#names);
  39. my $remain_child_process = scalar @names;

  40. $SIG{PIPE} = sub {
  41.     -- $remain_child_process;
  42.     print STDERR "pipe broken\n";
  43. };


  44. #==============================
  45. # main program
  46. #==============================
  47. my $now = time;
  48. my $pm =  new Parallel::ForkManager(scalar @names);
  49. foreach my $child ( 0 .. $#names ) {
  50.     my $pid = $pm->start($names[$child]) and next;
  51.     print "This is $names[$child], Child number $child: $\n";
  52.     work($child);
  53.     $pm->finish($child); # pass an exit code to finish
  54. }
  55. print "Waiting for Children...\n";
  56. show_progress();
  57. $pm->wait_all_children;
  58. $now = time - $now;
  59. printf("\n\nTotal run time: %02d:%02d:%02d\n\n", int($now / 3600), int(($now % 3600) / 60), int($now % 60));
  60. print "Everybody done!\n";


  61. #==============================
  62. # real work of child process
  63. #==============================
  64. sub work {
  65.     my $child = shift;

  66.     my $total = int(rand(20)) + 5;
  67.     foreach (1..$total) {
  68.         select(undef, undef, undef, 0.2);
  69.         sysopen (FIFO_W, $fpath, O_WRONLY) or die "can't write $fpath: $!";
  70.         print FIFO_W "child:$child,processed:$_,total:$total\n";
  71.         close FIFO_W;
  72.     }

  73.     sysopen (FIFO_W, $fpath, O_WRONLY) or die "can't write $fpath: $!";
  74.     print FIFO_W "$child over\n";
  75.     close FIFO_W;
  76. }


  77. #==================================================
  78. # receive progress data from child and display them
  79. #==================================================
  80. sub show_progress {
  81.     while ($remain_child_process) {
  82.         die "Pipe file disappeared" unless -p $fpath;
  83.         sysopen (FIFO_R, $fpath, O_RDONLY) or die "can't read $fpath: $!";
  84.         while(my $m = <FIFO_R>) {
  85.             if ($m =~ m/over/) {
  86.                 -- $remain_child_process;
  87.             }
  88.             else {
  89.                 #print $m;
  90.                 my ($child, $processed, $total) = $m =~ m/child:(\w+),processed:(\d+),total:(\d+)/;
  91.                 $childs->{$child}->{processed} = $processed;
  92.                 $childs->{$child}->{total} = $total;
  93.                 proc_bar($childs);
  94.             }
  95.         }
  96.         close FIFO_R;
  97.     }
  98.     $terminal->Tgoto('cm', 0, 5+2*@names, *STDOUT); #move cursor to bottom of screen
  99. }

  100. #=====================================
  101. # indicate the progress of comparation
  102. #=====================================
  103. sub proc_bar{
  104.     my $childs = shift;
  105.     local $| = 1;

  106.     $terminal->Tgoto('sc', undef, undef, *STDOUT); #save cursor
  107.     for my $c (sort keys %$childs) {
  108.         my $i = $childs->{$c}->{processed};
  109.         my $n = $childs->{$c}->{total};
  110.         my $name = $childs->{$c}->{name};
  111.         print "\r\033[36mchild: $c($name) [\033[33m".("#" x int(($i/$n)*50)).(" " x (50 - int(($i/$n)*50)))."\033[36m]";
  112.         printf("%2.1f%%\033[0m\n",$i/$n*100);
  113.     }
  114.     $terminal->Tgoto('rc', undef, undef, *STDOUT); #restore cursor

  115.     local $| = 0;
  116. }

复制代码

论坛徽章:
0
2 [报告]
发表于 2010-10-07 17:05 |只看该作者
支持一下,慢慢看~

论坛徽章:
0
3 [报告]
发表于 2010-10-09 16:38 |只看该作者
慢慢学习
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP