V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
oldbird
V2EX  ›  Python

c#窗体中用 cmd 方式执行 Python 文件,如何在文本框中输出 py 文件里的 print 值

  •  
  •   oldbird · 2019-03-06 17:35:29 +08:00 · 2942 次点击
    这是一个创建于 2100 天前的主题,其中的信息可能已经有所发展或是发生改变。

    python 文件里隔几秒会打印一个值,想把这些值同时显示在窗体里。 查了网上的资料,思路基本上是截取输出流, 现在自己能实现的是一次性显示所有的打印值,不知道怎么才能做到依次显示?

    16 条回复    2019-03-08 11:46:53 +08:00
    yicong135
        1
    yicong135  
       2019-03-06 17:58:17 +08:00 via Android
    你可以搜索下 c#获取命令行内容
    Youen
        2
    Youen  
       2019-03-06 19:19:28 +08:00
    我觉得可以参考 VSCODE debug python 的那种
    nanaw
        3
    nanaw  
       2019-03-06 19:47:30 +08:00 via Android
    用获取管道的函数获取命令返回的字符串 Python 里面 os.popen 这样的
    c#应该也有,
    没有的话就重定向到文件再读取出来(
    lihongjie0209
        4
    lihongjie0209  
       2019-03-06 19:53:16 +08:00
    查一下 window 中共享内存的方法
    bakabie
        5
    bakabie  
       2019-03-06 20:03:08 +08:00 via Android
    参考远程匿名管道。一个管道读一个管道写。
    以前远控木马常用技术(?
    oldbird
        6
    oldbird  
    OP
       2019-03-07 06:47:58 +08:00 via Android
    @yicong135 目前只做到了一次性获取所有控制台输出内容,不知道怎么按时间间隔依次获取,还望指点。
    yicong135
        7
    yicong135  
       2019-03-07 09:09:40 +08:00
    如果控制台输出没法满足你需求,那你可以用通讯手段,比如命名管道或者 socket
    sarlanori
        8
    sarlanori  
       2019-03-07 09:44:00 +08:00
    直接使用 Process 类的 OutputDataReceived 和 ErrorDataReceived 事件来获取进程输出和错误信息。

    记得要将 EnableRaisingEvents 设为 true,并在调用 Process.Start 后调用 BeginErrorReadLine 和 BeginOutputReadLine。
    oldbird
        9
    oldbird  
    OP
       2019-03-07 10:51:01 +08:00
    @sarlanori 这样是等 cmd 执行完一次性读取输出值,还是可以执行途中依次同步显示输出值?
    sarlanori
        10
    sarlanori  
       2019-03-07 13:13:11 +08:00
    实时同步触发,当目标进程打印一次,该事件触发一次。

    其实你自己试一下就知道了,就几行代码的事。
    oldbird
        11
    oldbird  
    OP
       2019-03-07 15:48:24 +08:00
    @sarlanori 试了以下代码,但是 richtextbox 控件中还是只能等 py 文件运行完才一次性显示所有的 print 输出,不知道怎么改。。。。
    ##aaa.py 每隔 2 秒打印一个值
    import time
    for i in range(0,5):
    print i
    time.sleep(2)

    ## c#代码段
    using (Process process = new System.Diagnostics.Process())
    {
    process.StartInfo.FileName = "python";
    process.StartInfo.Arguments = "aaa.py";
    // 必须禁用操作系统外壳程序
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;
    process.Start();

    // 异步获取命令行内容
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();

    // 为异步获取订阅事件
    process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
    process.ErrorDataReceived += new DataReceivedEventHandler(process_ErrorDataReceived);
    }
    oldbird
        12
    oldbird  
    OP
       2019-03-07 16:25:48 +08:00
    跟了一下代码,11 楼的方法是可行的。
    问题在于 richtextbox.text 的值的确是在动态更新的(采用 append 方式),但是控件中一直不显示,直到 cmd 运行完,才显示出来,所以只看到了最后一次的 text 值,即全部的输出内容。这个问题怎么解决呢?
    sarlanori
        13
    sarlanori  
       2019-03-07 18:10:32 +08:00
    @oldbird 估计是线程被阻塞了
    sarlanori
        14
    sarlanori  
       2019-03-08 10:16:26 +08:00
    @oldbird 刚才研究了一下,这个问题出在 python 代码里,你需要在每次 print 之后调用 sys.stdout.flush 及时将缓冲区里的内容 flush 出去,这样 C# 里回调就能触发了。
    oldbird
        16
    oldbird  
    OP
       2019-03-08 11:46:53 +08:00
    @sarlanori 感谢,确实是的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6019 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 02:05 · PVG 10:05 · LAX 18:05 · JFK 21:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.