Форма Windows — запуск скрипта Python, перенаправление вывода задерживается

Я запускаю форму Windows с фоновым работником для обновления текстового поля на основе вывода скрипта Python. Все работает довольно хорошо, за исключением того, что перенаправленный вывод не в реальном времени; его задержка довольно значительно.

Любые идеи, как я могу увеличить время отклика перенаправленных выходов?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.IO;

namespace JiraHeartBeat
{
    public partial class Form1 : Form
    {

        delegate void AppendTextDelegate(string text);
        BackgroundWorker Worker = new BackgroundWorker();

        public Form1()
        {
            InitializeComponent();

            Worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
            Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted);

        }

        void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            StartButton.PerformClick();
        }

        private void StartButton_Click(object sender, EventArgs e)
        {
            if (!Worker.IsBusy)
            {
                Worker.RunWorkerAsync();
            }
        }

        public void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            Process pro = new Process();
            pro.StartInfo.RedirectStandardOutput = true;
            pro.StartInfo.RedirectStandardError = true;
            pro.StartInfo.UseShellExecute = false;
            pro.StartInfo.CreateNoWindow = true;
            pro.EnableRaisingEvents = true;
            pro.OutputDataReceived += new DataReceivedEventHandler(OnDataReceived);
            pro.ErrorDataReceived += new DataReceivedEventHandler(OnDataReceived);

            pro.StartInfo.FileName = "C:\\Python27\\python.exe";
            pro.StartInfo.Arguments = "\"C:\\Python27\\myscript.py\"";

            try
            {
                pro.Start();
                pro.BeginOutputReadLine();
                pro.BeginErrorReadLine();
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            Thread.Sleep(5000 * 60);
        }


        public void OnDataReceived(object sender, DataReceivedEventArgs e)
        {

            if (e.Data != null)
            {
                string temp = (e.Data) + Environment.NewLine;
                appendText(temp);

            }
        }
        public void appendText(string text)
        {
            if (ResultTextBox.InvokeRequired)
            {
                ResultTextBox.Invoke(new AppendTextDelegate(appendText), new object[] { text });
            }
            else
            {
                ResultTextBox.AppendText(text);
            }
        }
    }
}

person Sugitime    schedule 31.10.2013    source источник


Ответы (2)


На самом деле проблема в том, что Python не перенаправляет вывод, пока сценарий не будет завершен. Я считаю, что IronPython будет перенаправлять во время работы скрипта (хотя это не проверялось), но, к сожалению, обычный Python должен дождаться завершения скрипта, прежде чем перенаправить вывод.

person Sugitime    schedule 05.11.2013

Попробуйте удалить строку ниже из Worker_DoWork, я подозреваю, что это задерживает выполнение события RunWorkerCompleted.

Thread.Sleep(5000 * 60);

ИЗМЕНИТЬ

Поскольку описанный выше подход был предпринят и не решил проблему полностью, я продолжил исследование и подтвердил, что при захвате вывода из скрипта Python ответ задерживается. Однако, добавив вызов sys.stdout.flush(), я смог добиться желаемого поведения. Вот скрипт Python, который я использовал, который успешно работал в моем тесте.

import time
import sys

for x in xrange(0,11):
    print x
    time.sleep(1)
    sys.stdout.flush()
person LeastOne    schedule 31.10.2013
comment
На самом деле проблема в том, что Python не перенаправляет вывод, пока сценарий не будет завершен. Я считаю, что IronPython будет перенаправлять во время работы скрипта, но, к сожалению, обычный Python этого не делает :( - person Sugitime; 31.10.2013
comment
Я запустил ваш код, чтобы подтвердить свои подозрения. Когда я запускаю его, первый вызов процесса немедленно выводится в TextBox, но второй вызов откладывается до завершения Thread.Sleep(5000 * 60);. Я вполне уверен, что это, по крайней мере, фактор, способствующий вашей проблеме. Я не запускал процесс Python, вместо этого я выполнил отдельное консольное приложение, которое я собрал вместе. Возможно, вы могли бы попробовать закомментировать строку просто в качестве теста и/или использовать другой процесс в качестве средства дальнейшего сужения проблемы. - person LeastOne; 31.10.2013
comment
Консольные приложения будут отвечать в режиме реального времени, а скрипты Python — нет. Создайте простой скрипт Python, который печатает от 1 до 10 с перерывом в 1 секунду между каждой печатью, и вы увидите, что даже если бы я переместил thread.sleep (что я и сделал. Я создал отдельный фоновый рабочий, который был запущен для запуска обратного отсчета после завершения Worker), он по-прежнему не будет выводиться в реальном времени. - person Sugitime; 01.11.2013