【问题标题】:Django: Logging from batch/cron scriptsDjango:从批处理/cron脚本记录
【发布时间】:2015-11-15 12:58:20
【问题描述】:

到目前为止,我们像这样运行 cronjobs:

@daily do_daily_magic > log/do_daily_magic.log

到目前为止,我们还没有使用 django 的日志记录配置:

https://docs.djangoproject.com/en/1.8/topics/logging/

但是我想改成默认的django方式。

如何为 django 编写一个将所有日志输出到标准输出的批处理脚本?

【问题讨论】:

    标签: python django batch-file logging


    【解决方案1】:

    在 settings.py 中定义日志记录如下:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'file': {
                'level': 'DEBUG',
                'class': 'logging.FileHandler',
                'filename': '/path/to/do_daily_magic.log',
            },
        },
        'loggers': {
            'myapp.myscript.logger': {
                'handlers': ['file'],
                'level': 'DEBUG',
                'propagate': True,
            },
        },
    }
    

    您可以使用 logger myapp.myscript.logger 直接从 django 将信息写入文件。

    import logging
    
    logger = logging.getLogger('myapp.myscript.logger')
    
    
    class Command(BaseCommand):
        def handle(self, *args, **options):
            # do some stuff
            logger.info("Some info for logs")
    

    但是,我建议您也继续使用 crontab 进行日志记录。因为它可以处理在调用 Django 之前发生的任何错误。例如,它还将处理缺少的 python 解释器或错误的环境。

    附:如果您只想将所有日志从 django 写入标准输出,请使用以下 logger 配置

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console': {
                'class': 'logging.StreamHandler',
            },
        },
        'loggers': {
            'myapp.myscript.logger': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': True,
            },
        },
    }
    

    【讨论】:

      【解决方案2】:

      我有一个类似的用例并使用custom management command 处理它。在我看来,它比独立的 python 脚本要优雅得多,因为一切都是自动设置的,我总是可以通过 manage.py 手动运行命令。

      你可以通过将你的逻辑放在一个模块中来做到这一点

      your_app/management/commands/your_daily_magic_command.py
      

      不要忘记也创建(如果它不存在):

      your_app/management/__init__.py
      your_app/management/commands/__init__.py
      

      your_daily_magic_command.py 内部,它应该看起来像这样:

      from django.core.management.base import BaseCommand, CommandError
      ##import logging
      ##logger = logging.getLogger(__name__)
      
      
      class Command(BaseCommand):
          #args = '<required_arg1> [optional_arg2]'
          help = 'Put your help text here to be shown in manage.py help'
      
          def handle(self, *args, **options):
              #if len(args) == 0:
              #    raise CommandError('Not enough arguments. Please see help')
              #if len(args) > 2:
              #    raise CommandError('Too many arguments. Please see help')
      
              self.stdout.write('Starting my daily magic stuff...')
              #self.stdout.write('Arguments: %s' % args)
      
              # Your daily magic logic here
      
              self.stdout.write('Finished my daily magic stuff :)')
              ##logger.debug("A debug message...")
              ##logger.info("...using django's logging mechanism")
      

      一件好事是它还可以为您处理命令行参数。在我的示例中,单个注释行向您展示了如何使用一个必需参数和一个可选参数,以便您可以从那里进行编辑。

      无需使用logging 包,您只需使用self.stdout.write(见代码)

      官方例子见django.core.mangement.commands.*

      运行你的命令:

      python /path/to/your/project/manage.py your_daily_magic_command
      

      如果你真的想使用带有 django 快捷方式的 python logging 包,你需要设置你的 settings.LOGGING。这是一个例子:

      LOGGING = {
          'version': 1,
          'disable_existing_loggers': False,
          'formatters': {
              'standard': {
                  # You can change your format here
                  'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
              },
          },
          'handlers': {
              'console_out': {
                  'level': 'DEBUG',
                  'class': 'logging.StreamHandler',
                  'formatter': 'standard',
                  # 'strm' in Python 2.6. See http://codeinthehole.com/writing/console-logging-to-stdout-in-django/
                  'stream': sys.stdout,
              },
              'console_err': {
                  'level': 'DEBUG',
                  'class': 'logging.StreamHandler',
                  'formatter': 'standard',
              }
          },
          'loggers': {
              'your_app_path.management.commands.your_daily_magic_command': {
                  'handlers': ['console_out'],
                  'level': 'DEBUG',  # DEBUG level is lower than INFO
                  'propagate': True,
              },
              # Default logger: http://stackoverflow.com/questions/5438642/django-setup-default-logging
              '': {
                  # For special handling, see http://code.activestate.com/recipes/576819-logging-to-console-without-surprises/
                  'handlers': ['console_err'],
                  'level': 'INFO',   # Show only INFO and up
                  'propagate': True,
              },
          }
      }
      

      在上面的 your_daily_magic_command.py 示例中,双注释 (##) 行向您展示了如何使用它。

      记录器名称可以是与您的settings.LOGGING['loggers'] 条目对应的任何名称,但使用__name__ 来引用当前模块是标准做法。

      【讨论】:

        【解决方案3】:

        查看console处理程序比通过logging.StreamHandler刷新数据,还记得比default behavior for logging.StreamHandler is loggin to stderr

        如果指定了流,实例将使用它来记录输出;否则,将使用sys.stderr

        您可以编写自己的handlerclass 来登录sys.stdoutmy_utils.py

        import logging, sys
        
        class StreamHandlerStOut( logging.StreamHandler )
            def __init__( self ):
                super(StreamHandlerStOut, self).__init__(sys.stderr) 
        

        并在 settings.py 上将您的新类设置为您的处理程序:

        import os
        LOGGING = {
            'version': 1,
            'disable_existing_loggers': False,
            'handlers': {
                'my_console': {
                    #'class': 'logging.StreamHandler',
                    'class': 'my_utils.StreamHandlerStOut',
                },
            },
            'loggers': {
                'my_logger': {
                    'handlers': ['my_console'],
                    'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
                },
            },
        }
        

        记得在你的 cron 脚本代码上use your logger

        【讨论】:

          【解决方案4】:

          如果您尝试从 Django 环境之外运行 python 脚本,那么您需要获取 Django 路径以获取从 Django 中使用的库和方法。这可以做到,但它有点脏。

          你的python脚本需要从Django获取信息,例如:

          import sys, os
          sys.path.append('/path/to/your/django/app')
          os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
          from django.conf import settings
          

          你可能想关注这个:http://www.b-list.org/weblog/2007/sep/22/standalone-django-scripts/

          从 python 代码中编写日志或输出而不是依赖于 stdout 更符合 Python 风格。如果您遵循这种方法,那么您的 cron 条目应该是

          @daily do_daily_magic 2>&1 |记录器

          它将获取所有 STDOUT 和 STDERR 并将其发送到记录器以被 syslog 捕获(例如 /var/log/sys.log)。由于您的 python 代码会将输出定向到它自己的文件,因此从 cron 条目中出来的唯一内容将是调试消息或未定向到日志的错误,包括 cron、权限、异常等问题,并且是正确旋转)

          【讨论】:

          • 感谢您提供此信息。是的,我们的解决方案很好。但是这个问题是关于将日志写入标准输出的。你的帖子是一个答案。但不是与这个问题相匹配的答案。
          猜你喜欢
          • 2011-06-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多