Python string formatting - limit string length, but trim string beginning
Asked Answered
P

4

14

I'm using Python standard logging module with custom formatter where I limit length of some fields. It uses standard % Python operator.

I can apply limit for percent-formatted string like this (this limits length to 10 chars):

>>> "%.10s" % "Lorem Ipsum"
'Lorem Ipsu'

Is it possible to trim it from the beginning, so the output is 'orem Ipsum' (without manipulating right-side argument)?

Plunder answered 23/10, 2014 at 15:40 Comment(2)
I don't think it's possible.Osmanli
It should be noted that "{:.10}".format("Lorem Ipsum") produces the same result using format as does %.Christan
B
13

Is it possible to trim it from the beginning with % formatting?

Python's % formatting comes from C's printf.

Note that the . indicates precision for a float. That it works on a string is a mere side effect, and unfortunately, there is no provision in the string formatting specification to accommodate stripping a string from the left to a fixed max width.

Therefore if you must strip a string to a fixed width from the end, I recommend to slice from a negative index. This operation is robust, and won't fail if the string is less than 10 chars.

>>> up_to_last_10_slice = slice(-10, None)
>>> 'Lorem Ipsum'[up_to_last_10_slice]
'orem Ipsum'
>>> 'Ipsum'[up_to_last_10_slice]
'Ipsum'

str.format also no help

str.format is of no help here, the width is a minimum width:

>>> '{lorem:>10}'.format(lorem='Lorem Ipsum')
'Lorem Ipsum'
>>> '{lorem:*>10}'.format(lorem='Lorem')
'*****Lorem'

(The asterisk, "*", is the fill character.)

Blakely answered 23/10, 2014 at 16:26 Comment(4)
Bingo. The "precision" truncation of string formatting (% and .format() inherently removes from the right hand side. So unless you use string truncation, reversing, or another alternative before submitting to formatting, seems impossible.Chirp
@JonathanEunice It's a pity that the documentation is so hard to find and unreadable. But .format documentation is fairly well documented and readable. It would have been easier to point to that documentation...Blakely
The .format documentation is here if you like it. I personally find it rather dense and frustrating. OTOH, it's a reference more than a how-to-use, and the underlying functionality and options are many and detailed.Chirp
@JonathanEunice No, I know where that documentation is. It's actually much easier to understand compared to printf docs. But to really understand it you need to spend some time with it. Same with the rest of the language spec: docs.python.org/reference/expressions.htmlBlakely
P
13

This can easily be done through slicing, so you do not require any string format manipulation to do your JOB

>>> "Lorem Ipsum"[-10:]
'orem Ipsum'
Panda answered 23/10, 2014 at 15:45 Comment(3)
Its good to downvote if the answer is not helpful, but can any one educate me why is it so?Panda
Yes, but that requirement can't be satisfied.Battles
This is not very helpful if you are trying to limit log output because then you get something like "{}.{}".format(str(myData)[-10:] ,maybe_dots[len(str(myData))>=10])) which is not very nice and may produce additional crashes. You want "<answer>.." or "<answer>" depending on length.Christan
B
13

Is it possible to trim it from the beginning with % formatting?

Python's % formatting comes from C's printf.

Note that the . indicates precision for a float. That it works on a string is a mere side effect, and unfortunately, there is no provision in the string formatting specification to accommodate stripping a string from the left to a fixed max width.

Therefore if you must strip a string to a fixed width from the end, I recommend to slice from a negative index. This operation is robust, and won't fail if the string is less than 10 chars.

>>> up_to_last_10_slice = slice(-10, None)
>>> 'Lorem Ipsum'[up_to_last_10_slice]
'orem Ipsum'
>>> 'Ipsum'[up_to_last_10_slice]
'Ipsum'

str.format also no help

str.format is of no help here, the width is a minimum width:

>>> '{lorem:>10}'.format(lorem='Lorem Ipsum')
'Lorem Ipsum'
>>> '{lorem:*>10}'.format(lorem='Lorem')
'*****Lorem'

(The asterisk, "*", is the fill character.)

Blakely answered 23/10, 2014 at 16:26 Comment(4)
Bingo. The "precision" truncation of string formatting (% and .format() inherently removes from the right hand side. So unless you use string truncation, reversing, or another alternative before submitting to formatting, seems impossible.Chirp
@JonathanEunice It's a pity that the documentation is so hard to find and unreadable. But .format documentation is fairly well documented and readable. It would have been easier to point to that documentation...Blakely
The .format documentation is here if you like it. I personally find it rather dense and frustrating. OTOH, it's a reference more than a how-to-use, and the underlying functionality and options are many and detailed.Chirp
@JonathanEunice No, I know where that documentation is. It's actually much easier to understand compared to printf docs. But to really understand it you need to spend some time with it. Same with the rest of the language spec: docs.python.org/reference/expressions.htmlBlakely
M
5

The equivalent to "%.10s" % "Lorem Ipsum" in modern Python would be:

Using str.format:

"{:.10}".format("Lorem Ipsum")

Using f-strings:

text = "Lorem Ipsum"
f"{text:.10}"
Metanephros answered 26/2, 2023 at 2:28 Comment(0)
D
4

I had the same question and came up with this solution using LogRecordFactory.

orig_factory = logging.getLogRecordFactory()

def record_factory(*args, **kwargs):
    record = orig_factory(*args, **kwargs)
    record.sname = record.name[-10:] if len(
        record.name) > 10 else record.name
    return record

logging.setLogRecordFactory(record_factory)

Here I am truncating the name to 10 characters and storing it in the attribute sname, which can be used as any other value.

%(sname)10s

It is possible to store the truncated name in record.name, but I wanted to keep the original name around too.

Dodd answered 6/7, 2018 at 6:25 Comment(1)
Actually this should be: %(sname).10sLawson

© 2022 - 2025 — McMap. All rights reserved.