[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
Sun Jun 21 09:07:40 UTC 2015


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

Status: Open
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-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