Python textwrap – Fix Your Multiline Strings Indentation

I’ve been writing a lot in python the last couple of months and most of my code is for a CLI oriented environment (Mostly Linux/Unix shell).

One of the most important things when you create CLI is the help and usage string – Mostly because other people will try to use it – But lets face it, that script you’ve written a month ago? You’ve probably completely forgotten how it works.

So writing help or usage usually means that you work with an external file or multiline string. Now with a file there is no problem but a multiline is a little problematic, For example:

def printUsage ():
   usage = '''backup-site OPTIONS backup|check|rotate SITE
This program backup your site.
Options:
     -f     Force the operation
Commands:
    ......
'''
   Rest of the code

Now when you write a multiline string you will use Enter for a new line. Python work on indent to cipher code blocks. Now the interpeter will understand that and most of text editors using Folds.

Yet this is sometimes look bad in your eye and might give you some problems reading your code.
But there is an easy solution:
textwrap.dedent()

Here is a simple example:

>>> import textwrap
u = '''
	Line A
	Line B
	  Line C
	Line D
	'''
>>> print u
 
	Line A
	Line B
	  Line C
	Line D
 
>>> print textwrap.dedent(u)
 
Line A
Line B
  Line C
Line D
 
>>>

As you can see the dedent function removed all the indent but still preserved the correct indentation inside the global indentation.
Thus you can use the dedent function while your code indentation preserved.

Only one little we need to do – Remove the first and last lines (you can see in the example that the new line is still being print.
You can remove the first line and the last line:

# Remove the first line:
u = u[u.find('\n')+1:]
# Remove the last line:
u = u[:u.rfind('\n')]
# Remove both the first and last line:
u = u[u.find('\n')+1:u.rfind('\n')]

So connecting all together:

>>> import textwrap
>>> u = '''
	Line A
	Line B
	  Line C
	Line D
	'''
>>> u = u[u.find('\n')+1:u.rfind('\n')]
>>> u = textwrap.dedent(u)
>>> u
'Line A\nLine B\n Line C\nLine D'
>>> print u
Line A
Line B
 Line C
Line D
>>>

So you can preserver your code indentation and yet print it correctly.

What is missing from here is the wrap for the text – Because textwrap is not working with multiline strings.

My next post will be about text wrapping for multiline text wrap.

Leave a Reply

Your email address will not be published. Required fields are marked *