[python-daemon-Bugs][315090] Redirecting `sys.stdout` fails when `sys.stdout` is not a real stream

python-daemon-bugs at alioth.debian.org python-daemon-bugs at alioth.debian.org
Fri Jul 10 12:04:39 UTC 2015


python-daemon-Bugs item #315090 was changed at 2015-07-10 12:04 by Torfus Polymorphus
You can respond by visiting: 
https://alioth.debian.org/tracker/?func=detail&atid=413098&aid=315090&group_id=100328

Status: Closed
Priority: 3
Submitted By: Torfus Polymorphus (torf-guest)
Assigned to: Nobody (None)
Summary: Redirecting `sys.stdout` fails when `sys.stdout` is not a real stream 


Initial Comment:
A feature of many Python testing frameworks (e.g. nose) is to capture output to STDOUT (the captured output is only displayed if a test fails). Usually, this is accomplished by replacing `sys.stdout` with another file-like object, e.g. a `cStringIO.StringIO` instance. However, this breaks DaemonContext, since DaemonContext tries to access `sys.stdout.fileno` in `redirect_stream` -- the capturing objects usually don't have a `fileno` attribute:

  File "/home/torf/projects/coba/venv/local/lib/python2.7/site-packages/daemon/daemon.py", line 380, in __enter__
    self.open()
  File "/home/torf/projects/coba/venv/local/lib/python2.7/site-packages/daemon/daemon.py", line 367, in open
    redirect_stream(sys.stdin, self.stdin)
  File "/home/torf/projects/coba/venv/local/lib/python2.7/site-packages/daemon/daemon.py", line 845, in redirect_stream
    os.dup2(target_fd, system_stream.fileno())
AttributeError: 'cStringIO.StringIO' object has no attribute 'fileno'

In my opinion, DaemonContext should handle this situation gracefully.


----------------------------------------------------------------------

Comment By: Torfus Polymorphus (torf-guest)
Date: 2015-07-10 12:04

Message:
It seems that this issue has already been reported w.r.t. nose, see for example

https://github.com/nose-devs/nose/issues/6
https://github.com/nose-devs/nose/issues/322

Thanks again for your time!


----------------------------------------------------------------------

Comment By: Ben Finney (bignose-guest)
Date: 2015-07-05 08:49

Message:
> I therefore suggest to close this ticket.

Shall do, thanks.

> I think the best place to fix this would actually be the testing framework itself, since obviously their replacement for `sys.stdout` should mimick `sys.stdout` as close as possible.

Good, that matches my position too.

I think this is a bug that deserves to be reported on Python's ‘unittest’, or ‘unittest.mock’, ‘nose’, or whatever other testing framework you think should be handling this gracefully.

Can you take the lead on that? If you would like my assistance on that, please contact me via my email address ‘ben+python at benfinney.id.au’.


----------------------------------------------------------------------

Comment By: Torfus Polymorphus (torf-guest)
Date: 2015-06-21 09:07

Message:
I think the best place to fix this would actually be the testing framework itself, since obviously their replacement for `sys.stdout` should mimick `sys.stdout` as close as possible.

Putting the responsibility for this on the developer who uses python-daemon, on the other hand, would mean that every developer who wants to test their daemon using such frameworks would have to implement a test double themself, leading to unnecessary code duplication across many projects.

My initial idea was to handle this on a higher level: Instead of duplicating file descriptors, replace the stream objects themselves, i.e. instead of

    redirect_stream(sys.stdout, self.stdout)

do

    sys.stdout = self.stdout or open(os.devnull, 'r+')

However, that doesn't change STDOUT for processes launched from the daemon (I thought that Python might handle this for us internally).

So it seems that, inside python-daemon, we cannot do much when we don't have a file descriptor (just as you said). I can't think of a clean workaround for when we don't have one, so you're probably right that python-daemon is not the right place to fix this. I therefore suggest to close this ticket.

The (hackish) workaround that I'm currently using in my own code is to restore `sys.stdout` to its original value (`sys.__stdout__`) for the call to `DaemonContext.open` and resetting it to whatever it was before afterwards. Obviously this is not an approach that works for all situations.

By the way, I tried to checkout the repository using the command given on the website (bzr checkout https://alioth.debian.org/anonscm/bzr/python-daemon/) but that didn't work:

    bzr: ERROR: Not a branch: "https://alioth.debian.org/anonscm/bzr/python-daemon/.bzr/branch/": location is a repository.

Thanks for the great work on python-daemon, it made my life a lot easier!

----------------------------------------------------------------------

Comment By: Ben Finney (bignose-guest)
Date: 2015-06-21 08:12

Message:
Yes, a standard-library StringIO will not work for redirection, because redirection of a stream's file handle requires that there *be* a file handle.

The recommendation, if your test cases require a test double for I/O streams, would be to subclass StringIO to add a file handle and use that for the test double. That applies with any library which needs file features StringIO does not have.

Patching ‘python-daemon’ to special-case fake file objects will only help with ‘python-daemon’; the correct solution IMO is to provide a test double that behaves the way is needed for whatever you're testing with.

I'm open to argument though. What would you suggest is appropriate behaviour for ‘python-daemon’ in the face of a file that isn't actually a file?


----------------------------------------------------------------------

You can respond by visiting: 
https://alioth.debian.org/tracker/?func=detail&atid=413098&aid=315090&group_id=100328



More information about the python-daemon-bugs mailing list