[Python 2/3] Parse the format string

There are currently three types of functionality in Python that are equivalent to C's sprintf. (Exclude f-string because it doesn't use a format string)

name? How to use
%-formatting fmt % values
str.format() fmt.format(*values) / fmt.format(**values)
Template strings string.Template(fmt).substitute(**values)

This article summarizes how to find out how many tuple elements or dictionary keys are required in the values part of the table above. To be honest, I think it's a fairly infrequently used knowledge, but it may be useful when you make your own Formatter by inheriting logging.Formatter.

Overview

--% -formatting → Fail format and see exception.

%-formatting (printf style formatting) Unlike the other two, I can't find a dedicated function for parsing in the standard package, so I'll do my best. This time I made a function to decipher based on the exception thrown back. If the type requested in the values part of fmt% values is a tuple, its length is returned, and if it is a dictionary, its key is returned.

def parse_printf_style_format(fmt):
    if not isinstance(fmt, (bytes, str)):
        raise TypeError('got ' + type(fmt).__name__)
        
    try:
        fmt % ()
    except TypeError as e:
        if e.args[0] == 'not enough arguments for format string':
            values = ()
        elif e.args[0] == 'format requires a mapping':
            values = {}
        else:
            raise
    else:
        return None
    
    if isinstance(values, tuple):
        while True:
            try:
                fmt % values
            except TypeError as e:
                if e.args[0] == 'not enough arguments for format string':
                    values += (0,)
                else:
                    raise ValueError('invalid format: ' + repr(fmt))
            else:
                return len(values)
    elif isinstance(values, dict):
        while True:
            try:
                fmt % values
            except TypeError as e:
                if e.args[0] == 'not enough arguments for format string':
                    raise ValueError('invalid format: ' + repr(fmt))
                else:
                    raise
            except KeyError as e:
                values[e.args[0]] = 0
            else:
                return tuple(values.keys())
    else:
        assert False

Example of use

>>> parse_printf_style_format('%d %s %x')
3
>>> parse_printf_style_format('%(foo)s, %(bar)d')
('foo', 'bar')

str.format()

It's a blow with string.Formatter (). parse (fmt). For details, refer to Official Document.

>>> import string
>>> fmt = '{foo:s}, {{bar:d}}, and {:f}'
>>> list(string.Formatter().parse(fmt))
[('', 'foo', 's', None),
 (', {', None, None, None),
 ('bar:d}', None, None, None),
 (', and ', '', 'f', None)]

Template strings

It is a blow with string.Template.pattern.finditer (fmt). The regular expression that matches the placeholder is stored in the pattern attribute.

>>> import string
>>> fmt = '${this_is_braced} $$this_is_escaped $@this_is_invalid $this_is_named'
>>> print(string.Template.pattern.pattern)
    \$(?:
      (?P<escaped>\$) |   # Escape sequence of two delimiters
      (?P<named>[_a-z][_a-z0-9]*)      |   # delimiter and a Python identifier
      {(?P<braced>[_a-z][_a-z0-9]*)}   |   # delimiter and a braced identifier
      (?P<invalid>)              # Other ill-formed delimiter exprs
    )
>>> [match.groupdict() for match in string.Template.pattern.finditer(fmt)]
[{'braced': 'this_is_braced', 'escaped': None, 'invalid': None, 'named': None},
 {'braced': None, 'escaped': '$', 'invalid': None, 'named': None},
 {'braced': None, 'escaped': None, 'invalid': '', 'named': None},
 {'braced': None, 'escaped': None, 'invalid': None, 'named': 'this_is_named'}]

Impressions

The cold treatment of % -formatting is terrible.

Recommended Posts

[Python 2/3] Parse the format string
Python string format
Python string format
Python indentation and string format
String format with Python% operator
String format
String format 2
Python string
[Python3] Format the character string using the variable name as the key.
Python: String concatenation
python string slice
python: Use the variables defined in the string format as they are
Escape curly braces in the format string
Python2 string type
Python # string type
format in python
Python string inversion
[Introduction to Python] How to write a character string with the format function
Let's parse the git commit log in Python!
[Python] matplotlib: Format the diagram for your dissertation
[Python] How to change the date format (display format)
json.dumping None in python returns the string null
String to Unicode Escape Sequence Format for Python
Find the maximum Python
String manipulation in python
Parse XML in Python
[Python] Multi-line string assignment
Python string manipulation master
the zen of Python
python> datetime> Get the datetime (eg 20151130) format string> print today.strftime ("% Y% m% d") / print "{:% Y% m% d}" .format ( today)
Image format in Python
[Python2] Date string-> UnixTime-> Date string
Python Pickle format notes
[Python] format methodical use
Random string generation (Python)
parse for format, for Jinja2 ...?
[Python] Split the date
Python3> documentation string / docstring
Python string processing illustration
Check if the string is a number in python
Parse a JSON string written to a file in Python
Cut a part of the string using a Python slice
python> datetime> From date string (ISO format: 2015-12-09 12:40:08) to datetime type
I tried to summarize the string operations of Python
python3 Measure the processing speed.
[python] Convert date to string
Easily format JSON in Python
Find out the apparent width of a string in python
Towards the retirement of Python2
Download the file in Python
Remove double-byte spaces before and after the character string (python)
String object methods in Python
Find the difference in Python
[Python] Use a string sequence
Compare the Python array-like guys
About the Python module venv
Get the MIME type in Python and determine the file format
About the ease of Python
About the enumerate function (python)
[Python] Adjusting the color bar
[Python] Get the previous month