v217
v217

Reputation: 805

How to truncate and pad in python3 using just str.format?

I would like to do this:

'{pathname:>90}'.format(pathname='abcde')[-2:]

using string formatting instead of array indexing. So the result would be 'de' or in the case of pathname='e' the result would be ' e' with a space before e. If the index would be [2:] this question would be answered by How to truncate a string using str.format in Python?

I need this in the following example:

import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.INFO,style='{',format='{pathname:>90}{lineno:4d}{msg}')
logging.info('k')

Upvotes: 2

Views: 535

Answers (1)

Jean-François Fabre
Jean-François Fabre

Reputation: 140316

The precision trick (using a precision format) doesn't work. Only works to truncate the end of the string.

a workaround would be to slice the string before passing it to str.format:

>>> '{pathname:>2}'.format(pathname='abcde'[-2:])
'de'
>>> '{pathname:>2}'.format(pathname='e'[-2:])
' e'

since you cannot control the arguments passed to format, you could create a subclass of str and redefine format so when it meets pathname in the keyword arguments it truncates, then calls original str.format method.

Small self-contained example:

class TruncatePathnameStr(str):
    def format(self,*args,**kwargs):
        if "pathname" in kwargs:
            # truncate
            kwargs["pathname"] = kwargs["pathname"][-2:]
        return str.format(self,*args,**kwargs)

s = TruncatePathnameStr('##{pathname:>4}##')

print(s.format(pathname='abcde'))

that prints:

##  de##

use it in your real-life example:

logging.basicConfig(stream=sys.stdout, level=logging.INFO,style='{',
                    format=TruncatePathnameStr('{pathname:>90}{lineno:4d}{msg}'))

Upvotes: 3

Related Questions