{"id":691,"date":"2015-04-25T18:35:30","date_gmt":"2015-04-26T00:35:30","guid":{"rendered":"http:\/\/www.crccheck.com\/blog\/?p=691"},"modified":"2016-04-22T22:27:19","modified_gmt":"2016-04-23T04:27:19","slug":"django-management-commands-and-verbosity","status":"publish","type":"post","link":"https:\/\/www.crccheck.com\/blog\/django-management-commands-and-verbosity\/","title":{"rendered":"Django management commands and verbosity"},"content":{"rendered":"<p><a href=\"http:\/\/www.crccheck.com\/blog\/wp-content\/uploads\/2015\/04\/log.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-715\" src=\"http:\/\/www.crccheck.com\/blog\/wp-content\/uploads\/2015\/04\/log-300x245.png\" alt=\"Ren and Stimpy\" width=\"300\" height=\"245\" \/><\/a><\/p>\n<p>[update: This post has been corrected, thanks to my commenters for your feedback]<\/p>\n<p>Every Django management command gets the <code>verbosity<\/code> option for free. You may recognize this:<\/p>\n<pre><code>optional arguments:\r\n  -h, --help            show this help message and exit\r\n  -v {0,1,2,3}, --verbosity {0,1,2,3}\r\n                        Verbosity level; 0=minimal output, 1=normal output,\r\n                        2=verbose output, 3=very verbose output<\/code><\/pre>\n<p>We rarely use it because doing so usually means lots of if statements scattered through our code to support this. If you&#8217;re writing quick n&#8217; dirty code, this may look familiar in your management commands:<\/p>\n<pre><code>\r\nif options.get('verbosity') == 3:\r\n    print('hi')<\/code><\/pre>\n<p>In a recent Django project, I came up with a few lines of boilerplate to support the verbosity option, assuming you&#8217;re using also the <code>logging<\/code> library and not relying on <code>print<\/code>:<\/p>\n<pre><code>\r\nimport logging\r\nclass Command(BaseCommand):\r\n    def handle(self, *args, **options):\r\n        verbosity = options.get('verbosity')\r\n        if verbosity == 0:\r\n            logging.getLogger('my_command').setLevel(logging.WARN)\r\n        elif verbosity == 1:  # default\r\n            logging.getLogger('my_command').setLevel(logging.INFO)\r\n        elif verbosity &gt; 1:\r\n            logging.getLogger('my_command').setLevel(logging.DEBUG)\r\n        if verbosity &gt; 2:\r\n            logging.getLogger().setLevel(logging.DEBUG)<\/code><\/pre>\n<p><a href=\"https:\/\/github.com\/texas\/tx_mixed_beverages\/blob\/master\/mixed_beverages\/apps\/receipts\/management\/commands\/geocode.py\" target=\"_blank\">github.com\/texas\/tx_mixed_beverages\/blob\/master\/mixed_beverages\/apps\/receipts\/management\/commands\/geocode.py<\/a><\/p>\n<p>So what does this do?<\/p>\n<p>At the default verbosity, <strong>1<\/strong>, I display <code>INFO<\/code> logging statements from my command. Increasing verbosity to <strong>2<\/strong>, I also display <code>DEBUG<\/code> logs from my command. And going all the way to verbosity <strong>3<\/strong>, I also enable all logging statements that reach the root logger.<\/p>\n<p>Go forth and log!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>[update: This post has been corrected, thanks to my commenters for your feedback] Every Django management command gets the verbosity option for free. You may recognize this: optional arguments: -h, &#8211;help show this help message and exit -v {0,1,2,3}, &#8211;verbosity {0,1,2,3} Verbosity level; 0=minimal output, 1=normal output, 2=verbose output, 3=very verbose output We rarely use&hellip;<\/p>\n <a href=\"https:\/\/www.crccheck.com\/blog\/django-management-commands-and-verbosity\/\" title=\"Django management commands and verbosity\" class=\"entry-more-link\"><span>Read More<\/span> <span class=\"screen-reader-text\">Django management commands and verbosity<\/span><\/a>","protected":false},"author":2,"featured_media":715,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[47,4,78],"tags":[51,48],"class_list":["entry","author-showmewhatyougot","post-691","post","type-post","status-publish","format-standard","has-post-thumbnail","category-meh-practices","category-technical","category-patterns","tag-django","tag-python"],"_links":{"self":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/691","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/comments?post=691"}],"version-history":[{"count":10,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/691\/revisions"}],"predecessor-version":[{"id":791,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/691\/revisions\/791"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/media\/715"}],"wp:attachment":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/media?parent=691"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/categories?post=691"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/tags?post=691"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}