0

Background: I've noticed that the trick nohup python test.py & usually doesn't work because the output is not saved correctly in real-time in nohup.out. The solutions given in this famous question (such as nohup python -u) don't always work, as shown in my other question here.

Question: I have used print(...) everywhere in my code, so I don't want to change this and replace it by another logging function. Is it possible to redefine print to do this instead:

from __future__ import print_function

def print(s):
    with open('out.txt', 'a+') as f:
        f.write(str(s) + '\n')
    old_print(s)     # how to print it with the standard print too?
Basj
  • 41,386
  • 99
  • 383
  • 673
  • What's wrong with the first answer to your earlier question? – user2357112 Sep 30 '17 at 16:09
  • @user2357112 if I remember well, solutions with `flush` didn't work in 100% of the cases for me. – Basj Sep 30 '17 at 16:11
  • If `flush` didn't work for you, there's no reason to expect `close` to work any better. You should probably look into the root cause of your nohup problems; what you're doing now is basically shotgun debugging. – user2357112 Sep 30 '17 at 16:12
  • Open, write, close would be fine for me (already tested), and then I would be 100% sure it will work. – Basj Sep 30 '17 at 16:15

1 Answers1

0

Well, you can override the builtin function.

Consider this test.py:

from __future__ import print_function

def new_print(*args, **kwargs):
    old_print('HELLO!')

import __builtin__
old_print = __builtin__.print
__builtin__.print = new_print

print(100)  # -> HELLO!
old_print(200)  # -> 200

This also works if you redefine the builtin function only once in a sigle module, and then just import it -- it will affect the whole app.

from __future__ import print_function
import test

print(300)  # HELLO!

But you still have to import from future in py2, always. Otherwise, print will not be a builtin function, but an operator, and thus never overridden.

This trick will also work in py3, with the exception that the module name is builtins. So the code could be like this:

from __future__ import print_function

def new_print(*args, **kwargs):
    old_print('HELLO!')

try:
    import __builtin__ as bi  # py2
except ImportError:
    import builtins as bi # py3

old_print = bi.print
bi.print = new_print

print(100)
old_print(200)
Sergey Vasilyev
  • 3,919
  • 3
  • 26
  • 37