代码之家  ›  专栏  ›  技术社区  ›  zhili

TCL利用管道和文件事件来维护子流程

  •  0
  • zhili  · 技术社区  · 1 周前

    我正在尝试在tcl中设置子流程管理的演示。这就是我迄今为止所做的

    proc receive {chan work_pool channel_id finish} {
        upvar 1 work_pool tmp_pool
        upvar 1 finish tmp_finish
        gets $chan line
        puts $line
        if {[eof $chan]} {
            close $chan
            # remove idx from work pool
            set idx [lsearch $tmp_pool $channel_id]
            set tmp_pool [lreplace $tmp_pool $idx $idx]
            if { [llength $tmp_pool] } {
            } else {
                set tmp_finish 1
            }
        }
    }
    
    
    set command1 {cmd /c "python py_script.py -n PRO1 -l 10"} 
    set channel1 [open |[concat $command1 2>@1]]
    
    
    fconfigure $channel1 -blocking 0 -buffering line
    
    set finish 0
    set work_pool [list 1]
    
    fileevent $channel1 readable [list receive $channel1 $work_pool 1 $finish]
    
    vwait finish
    

    这个脚本调用windows系统中的一个命令,该命令执行python脚本来打印计数器值(在这种情况下,它计数为10) fileevent用于附加一个名为“receive”的回调进程,以检索python stdout,然后在tcl进程中打印/放入。当检测到EOF时,回调进程将finish设置为1,这将导致整个过程的结束。

    python脚本包含以下代码,这些代码只需通过1秒的步骤将值计数到args.limit。

    import argparse, time
    parser = argparse.ArgumentParser()
    parser.add_argument("-n", "--name", type=str, default="default",
                        help="name")
    parser.add_argument("-l", "--limit", type=int, default=300,
                        help="count limit")
    args = parser.parse_args()
    a=0
    while(1):
        time.sleep(1)
        a=a+1
        print(f"{args.name}:timer value: {a}")
        if a>=args.limit:
            break
      
    

    我希望python脚本以1秒的间隔将每个数字打印到stdout。因此,tcl还应该以每秒一次的频率检索和打印这些数字。 例如

    PRO1:timer value: 1
    (1s)
    PRO1:timer value: 2
    (1s)
    PRO1:timer value: 3
    (1s)
    PRO1:timer value: 4
    (1s)
    PRO1:timer value: 5
    (1s)
    PRO1:timer value: 6
    (1s)
    PRO1:timer value: 7
    (1s)
    PRO1:timer value: 8
    (1s)
    PRO1:timer value: 9
    (1s)
    PRO1:timer value: 10
    

    然而,结果是10秒后批量打印10个数字

    (10s)
    PRO1:timer value: 1
    PRO1:timer value: 2
    PRO1:timer value: 3
    PRO1:timer value: 4
    PRO1:timer value: 5
    PRO1:timer value: 6
    PRO1:timer value: 7
    PRO1:timer value: 8
    PRO1:timer value: 9
    PRO1:timer value: 10
    

    有人能帮我找出这种不匹配的根源吗

    1 回复  |  直到 1 周前
        1
  •  2
  •   Schelte Bron    1 周前

    问题出在您的python脚本上。在管线中运行时,不会冲洗每条管线。只有当脚本完成时,才会刷新所有输出。尝试添加 sys.stdout.flush() 之后 print 命令

    我怀疑当您通过管道传输python命令的输出时,也会看到同样的效果 type (至少我在linux上测试时用 cat ; 我不使用窗户)。