0

I would like to monitor the progress of a given Python function (for those that know it, GridSearchCV from machine learning package Scikit Learn) during its execution. To do so, given the function has a parameter verbose, I can set the verbosity to be 1 or 10, whatever. However, I would also like to have some kind of time monitoring. The idea I had was to print on the console a timer each time something is printed in the console (in this case, printings would come from the activation of the verbosity of GridSearchCV), let's call this the printing function.

My questions are the following:

  • Is there a way in Python to execute a program when something is printed in the console?
  • A difficulty I see here is that, when I execute all these instructions (function GridSearchCV, the printing function), I am afraid what will happen is that GridSearchCV will be executed entirely, and then all the timers will be printed at the end. Is there a way to avoid this?
Daneel Olivaw
  • 2,077
  • 4
  • 15
  • 23
  • Check whether `GridSearchCV()` provides a proper progress API (e.g., whether it accepts a callback that is called periodically (such as [`reporthook` in urlretrieve()](https://docs.python.org/3/library/urllib.request.html#urllib.request.urlretrieve)) or whether it prints progress info to a socket, pipe that you can provide). – jfs Jan 10 '16 at 16:20

1 Answers1

0

This is possible by redirecting sys.stdout to your own custom class that can add information into the output. Here is an example of how that could be achieved. I pass in a datetime object to use as the reference to compute how much time has elapsed. Then when anything is printed to stdout, CustomStdout.write() is called and I then evaluate how much time has elapsed since the reference time and insert that information into the text being displayed, then display it using the initial stdout.

import sys
import time

from datetime import datetime


class CustomStdout():
    def __init__(self, start_time=None):
        self.stdout = sys.stdout
        self.start_time = start_time or datetime.now()

    def write(self, text):
        elapsed = datetime.now() - self.start_time

        text = text.rstrip()
        if len(text) == 0:
            return

        elapsed_str = '[%d.%03d seconds]' % (elapsed.seconds, elapsed.microseconds / 1000.)
        self.stdout.write('%s %s\n' % (elapsed_str, text))


print 'Printing before stdout redirect'

# Redirect stdout
sys.stdout = CustomStdout()

print 'Stdout now redirected'
print 'About to sleep 5 seconds'
time.sleep(5)
print 'Slept 5 seconds'

The output is

Printing before stdout redirect
[0.000 seconds] Stdout now redirected
[0.000 seconds] About to sleep 5 seconds
[5.004 seconds] Slept 5 seconds
Suever
  • 64,497
  • 14
  • 82
  • 101
  • it won't work if `GridSearchV()` uses [C stdout or prints at a file descriptor level (e.g., if it spawns subprocesses)](http://stackoverflow.com/a/22434262/4279) – jfs Jan 10 '16 at 16:18