ayushxx7 / dotfiles

My custom config files. Mostly, my vimrc.
2 stars 1 forks source link

Python: Convert Print Statements to Log Statements #2

Closed ayushxx7 closed 3 years ago

ayushxx7 commented 3 years ago

I want to write or find a plugin that helps me convert print statements to log statements in Python 3.

Consider a situation: I am writing some code, I want to add a feature based around some API, I quickly write a couple lines of code and add a bunch of print statements here and there that help me in understanding what the current state of the program is.

print("API response", response)
print(val1, val2)
print("I am a string with no variables")
print(f"I am an f-string so I will have {curly} {variables} here and there")
print(traceback.format_exc())

I want to be able to convert all these to log statements:

log.info(f"API response {response}")
log.info(f"{val1} {val2}"4)
log.info("I am a string with no variables")
log.info(f"I am an f-string so I will have {curly} {variables} here and there")
log.error(f"{traceback.format_exc()}")

In case of f-strings, it is a simple find and replace, but in all other cases, there's a lot of hassle around converting the print statement to a proper format before I can log it.

So far, I have written some custom mappings which use the surround.vim plugin:

"wrap value in bracket with f-string
nmap <leader>w ysib"ysi"}F"if<Esc>
"change print to log.info
nmap <leader>y csflog.info<Esc><leader>w
nmap <leader>wt _ys$}ysa}"If<Esc>_ys$)Ilog.error<Esc>
"maybe add map for direct writing the whole statement?
nmap <leader>yt Ilog.error(f"{traceback.format_exc()}")<Esc>

But they are very limited in usage

Asked on Stackoverflow & Reddit

ayushxx7 commented 3 years ago

Posting on r/vim helped! This solution is working.

The test script:

import logging, traceback

logging.basicConfig(filename='example.log', level=logging.DEBUG)

response = 'resp'
val1 = val2 = '1'

curly = "CURLY"
variables = "VARIABLES"

print("API response", response)

print(val1, val2)

print("I am a string with no variables")

print(f"I am an f-string so I will have {curly} {variables} here and there")

try:
    test
except:
    print(traceback.format_exc())

Running this in vim:

%s/print(\(.*\))/log.info(" ".join([\1]))/

Converts it to:

import logging, traceback

logging.basicConfig(filename='example.log', level=logging.DEBUG)

response = 'resp'
val1 = val2 = '1'

curly = "CURLY"
variables = "VARIABLES"

logging.info(" ".join(["API response", response]))

logging.info(" ".join([val1, val2]))

logging.info(" ".join(["I am a string with no variables"]))

logging.info(" ".join([f"I am an f-string so I will have {curly} {variables} here and there"]))

try:
    test
except:
    logging.info(" ".join([traceback.format_exc()]))

After the modified test.py file is executed, this is what example.log looks like:

INFO:root:API response resp
INFO:root:1 1
INFO:root:I am a string with no variables
INFO:root:I am an f-string so I will have CURLY VARIABLES here and there
INFO:root:Traceback (most recent call last):
  File "test.py", line 20, in <module>
    test
NameError: name 'test' is not defined

That is exactly what I wanted! Thanks xigoi

ayushxx7 commented 3 years ago

Fails in case one of the arguments is an integer.

    log.info(" ".join(['Iterations:', iterations]))
TypeError: sequence item 1: expected str instance, int found