3

I want to redirect all the output of my django (1.10.4) app to a file

Firstly, I tried:

python manage.py runserver 0.0.0.0:8000 >test.log 2>&1

But it doesn't redirect the output of the print command.

For example, in my code there is a statement:

print ('query_content:')

using command:

python manage.py runserver 0.0.0.0:8000

I can see that 'query_content:' is printed out on the screen.

But with :

python manage.py runserver 0.0.0.0:8000 >test.log 2>&1

In the test.log, there are only something like this:

[05/Nov/2017 20:38:20] "GET ... HTTP/1.1" 200 22404
[05/Nov/2017 20:38:26] "POST ... HTTP/1.1" 200 13
[05/Nov/2017 20:38:26] "GET .... HTTP/1.1" 200 16800
[05/Nov/2017 20:38:30] "GET ... 200 22430
...

One solution is:

import sys
sys.stdout = open('file', 'w')
print 'test'

But sometimes it is impossible to change the python code, is there any solution?

update:

I found that if the log file already exists, then everything is fine. But if I specify a new file name, then the output of python "print ..." statement cannot save the log file.

camino
  • 10,085
  • 20
  • 64
  • 115
  • Relevant: https://askubuntu.com/questions/420981/how-do-i-save-terminal-output-to-a-file – 0 _ Nov 06 '17 at 01:54
  • 2
    It's possible that the expected output is actually being correctly output, but it is buffered, so might not appear where you expect, if it is mixed with stderr output. Consider using the "-u" option to python when you start the server (that can affect performance) – John Anderson Nov 06 '17 at 02:00
  • Can't reproduce. Works fine in my Django 1.10. – randomir Nov 06 '17 at 02:05
  • @JohnAnderson It seems that the issue is related to cache. – camino Nov 07 '17 at 02:13
  • There is no way, you can not interfere with a process except the source code. You can do this by listening to the 8000 port of your local loopback address (raw socket). – dsgdfg Dec 29 '17 at 05:54
  • Which shell are you using, if you use bash it should create the file if it doesn't exists? And it looks like something else is also writing to the file. It can be that they interfere with each other. – rfkortekaas Dec 29 '17 at 16:08
  • Hey @camino, I was wondering, did you find my answer helpful? – John Moutafis Dec 31 '17 at 10:54
  • @JohnMoutafis it works, thanks – camino Dec 31 '17 at 16:09

3 Answers3

1

I believe that > writes to the file test.log whatever gets logged to console from Django.
print('query_content:') is not getting logged, therefore is not part of Django output.

You need to create a logger for your application:

  1. In settings.py add:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': True,
        'formatters': {
        'standard': {
            'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
            'datefmt' : "%d/%b/%Y %H:%M:%S"
        },
    },
    'handlers': {
        # This logs to the console
        'console':{
            'level':'INFO',
            'class':'logging.StreamHandler',
            'formatter': 'standard'
        },
    },
    'loggers': {
        'django': {
            'handlers':['console'],
            'propagate': True,
            'level':'INFO',
         },
    },
    
  2. Add the following were you want to log something:

    import logging
    mylogger = logging.getLogger(__name__)
    
    
    ...
    logger.info('query content: {}'.format(your_query_content))
    ...
    

Although the above solves your immediate problem, you can take it a step further:

Add a file handler in your LOGGER configuration:

  1. On handlers add:

    'file': {  
        'class': 'logging.FileHandler',
        'filename': 'a/file/location/logs.log',  
        'formatter': 'standard'
    },
    
  2. On loggers.django update the handlers:

    'handlers':['console', 'file'], 
    

You can customize the above even further, but that is another subject:

More info on python and django logging:

  1. https://docs.python.org/3/library/logging.html
  2. https://docs.djangoproject.com/en/2.0/topics/logging/
John Moutafis
  • 22,254
  • 11
  • 68
  • 112
  • Looks like you are right, thank you! I'll try your suggestion tomorrow – int_ua Dec 29 '17 at 19:46
  • @int_ua Let me know the outcome. I would suggest using the file logging method! – John Moutafis Dec 29 '17 at 21:01
  • TL;DR: you are getting the bounty. In the process I found the real reason of my problem and I'll post it as a separate answer. Also, I don't have time to really test this suggestion, but it's definitely interesting, so I'm awarding the bounty. Real testing is up to you or any future readers. – int_ua Dec 30 '17 at 13:03
  • @int_ua Ok mate! Happy coding, looking forward to your answer! – John Moutafis Dec 30 '17 at 13:05
0

I think this shell command maybe can output the result.

python manage.py runserver 0.0.0.0:8000 2>&1 | tee file.txt
Edge Li
  • 1
  • 1
0

TL;DR: if you have a loop in the end of a file you are feeding to manage.py shell add two newlines in the end.

In my case the reason prints were not present in the stdout was because they were never really executed in the first place. They were in a for loop that was at the end of file without two newlines or a newline and any other line (with a comment) after it. This way the shell was left waiting for a for loop code to be finished and it never was.

int_ua
  • 1,646
  • 2
  • 18
  • 32