0

There is a function named redirect which temporarily redirects operations on file source to file target.

    def redirect(source, target):
    source.flush()
    fd = source.fileno()
    with os.fdopen(os.dup(fd), source.mode) as source2:
        os.dup2(target.fileno(), fd)
        try:
            yield
        finally:
            source.flush()
            os.dup2(source2.fileno(), fd)

It was being called from the same module as

    with tempfile.TemporaryFile() as tmp:
        with redirect(sys.stdout, tmp), nogil:

Upon compiling, it used to generate an AttributeError

AttributeError: StringIO instance has no attribute 'fileno'

at the line fd = source.fileno().

But when I replaced sys.stdout with sys.__stdout__, there was no such error, and the tests passed successfully.

Now I'm really puzzled, why __stdout__ worked but not stdout.

Himanshu Mishra
  • 8,510
  • 12
  • 37
  • 74
  • Are you running your program from within the IDLE environment, or perhaps from another IDE? I think if you run your program from the system command line, you'll get an actual file for `sys.stdout`. – Greg Hewgill Jun 21 '15 at 04:10
  • I was running nosetests from terminal – Himanshu Mishra Jun 21 '15 at 04:20
  • 3
    Ah, yes the implementation of nosetests probably replaces `sys.stdout` with a `StringIO` object so that it can capture the output easily. It sounds like nosetests is not compatible with the function you're trying to run under it. – Greg Hewgill Jun 21 '15 at 04:26
  • 1
    It seems `nosetests` provides an option for this. `nosetests -s` works. – Himanshu Mishra Jun 21 '15 at 05:02
  • related: [Redirect stdout to a file in Python?](http://stackoverflow.com/q/4675728/4279) – jfs Jun 21 '15 at 10:21

1 Answers1

0

As Greg mentioned in the comments, that wouldn't work. What I normally do is temporarily change my stdout.

@contextmanager
def replace_stdout(replacement):
    _stdout = sys.stdout
    sys.stdout = replacement
    try:
        yield
    finally:
        sys.stdout = _stdout

And use that context manager with :

with tempfile.TemporaryFile() as tmp:
    with replace_stdout(sys.stdout, tmp):

This usages doesn't care whether the initial stdout has a FD or not.

AbdealiLoKo
  • 3,261
  • 2
  • 20
  • 36