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

Martin Wallgren
  • 503
  • 5
  • 11
Łukasz Rogalski
  • 22,092
  • 8
  • 59
  • 93

4 Answers4

11

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'
Abhijit
  • 62,056
  • 18
  • 131
  • 204
  • Its good to downvote if the answer is not helpful, but can any one educate me why is it so? – Abhijit Oct 23 '14 at 15:49
  • Yes, but that requirement can't be satisfied. – Chinmay Kanchi Oct 23 '14 at 18:02
  • 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 ".." or "" depending on length. – user6830669 Jan 05 '23 at 08:24
11

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

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
  • 2
    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. – Jonathan Eunice Oct 23 '14 at 16:37
  • @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... – Russia Must Remove Putin Oct 23 '14 at 16:47
  • The `.format` [documentation is here](https://docs.python.org/2/library/string.html#format-string-syntax) 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. – Jonathan Eunice Oct 23 '14 at 17:31
  • @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: https://docs.python.org/reference/expressions.html – Russia Must Remove Putin Oct 23 '14 at 17:44
3

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.

Martin Wallgren
  • 503
  • 5
  • 11
1

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}"