1

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

3
  • 1
    Welcome to Vi and Vim! This turns out to be difficult even with a macro, lots of edge-cases to consider. Obviously converting a general form into an f-string would solve the issue; you could do the print -> log.whatever afterwards. – D. Ben Knoble Apr 15 at 19:56
  • 1
    I think it would be far easier to achieve what you want in Python than in vim. Simply add a new function to take in args like ...(*args), and then call logs.info(" ".join(args)). And maybe a second function to call logs.error(" ".join(args)). Once you have those functions, then use vim to (e.g.) :%s/\<print(/print_log(/c – jalanb Apr 17 at 21:36
  • thanks, @jalanb, I have posted a solution to this question. which is similar to your approach, but depends completely on Vim with no additional steps other than a substitution. – Ayush Mandowara Apr 18 at 11:26
1

A substitution like this works for all scenarios:

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

  • Grab everything within print brackets (.*) using regex
  • replace the match with a join statement surrounding the match
  • replace the print with log.info (or whatever is required)

Here is the test script if anyone wants to try it for themselves:

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())

Note: I found the solution here. I also documented the question & answer in this issue & PR.

Thanks for your response @janand & @Ben Knoble

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.