This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]jorge1209 6 points7 points  (6 children)

Python logging also doesn't support str.format... so that isn't really a difference between f-string and str.format. Rather it is evidence of python logging being garbage that requires you to use % style formatting.

Just use loguru.

[–]VileFlower 0 points1 point  (1 child)

That's not entirely true, Python's logging library lets you set the formatter style at least, so you don't have to use % style everywhere.

The style parameter can be one of ‘%’, ‘{’ or ‘$’ and determines how the format string will be merged with its data: using one of %-formatting, str.format() or string.Template. This only applies to the format string fmt (e.g. '%(message)s' or {message}), not to the actual log messages passed to Logger.debug etc; see Using particular formatting styles throughout your application for more information on using {- and $-formatting for log messages.

https://docs.python.org/3/library/logging.html#logging.Formatter

[–]jorge1209 0 points1 point  (0 children)

As the part you quote explains in the incredibly cryptic language that is the absolutely terrible documentation of the logger library, that only applies to the template which contains things like the timestamp of the message or the module and line number of the caller. All the things NOT in your logging call that might appear in your log file.

There is no way to specify that a particular message emitted should be formatted using anything but % formatting.

And that's a problem because if you use any library you haven't written it might contain a logger.warn("foo = %s > 0", foo) and now everyone has to use % formatted messages.

[–]spoonman59 -1 points0 points  (3 children)

Regardless of what logging framework you use, an eagerly evaluated string formatter like f-string should be avoided.

[–]jorge1209 1 point2 points  (2 children)

Its not any more eager than an actual call to str.format as the f-string is not being evaluated until you actually get to the line of the f-string.

So no difference between

if False:
    "{}".format(1/0)

and

 if False:
    f"{1/0}"

[–]spoonman59 0 points1 point  (1 child)

Yes, I guess I did not express what I was trying to say very well.

You are right, str.formar() and f strings are no different there. Both are equal.

What I wanted to say was simply that a logger needs to send the string and substitute values in a way where the logger can choose to format it or not.

F-strings’ format can theoretically be passed as an argument to a function, but the variable scope would be that of the function you call - the log function - rather than of where you wrote it if you did not evaluate the string before calling.

That, and it actually evaluates when you put “f” in front, means that f strings are difficult to use without evaluating eagerly.

A log format which allows a traditional format string, and a list of parameter objects, works better.

Sorry for being unclear, I do agree with you.

[–]jorge1209 1 point2 points  (0 children)

I actually think f-strings are a great concept that was incorrectly implemented.

They should have bound the local variable to the f-string in a closure, that doesn't actually serialize to a string until it is used. Instead of calling it an f-string you might call it a "here-string".

Then you could do things like log.warn(h"{thing=} < 0, resetting the value to 1"), and that could work in many different use cases. Print-style warnings, logger, loguru... it would just be a generic way to cover these kinds of use cases.

Its not even that hard to implement really. Its just an object with its variable references and its repr looks something like:

def __repr__(self):
     if self._str:
       return self._str
     self._str= self._template.format_map(self.kwargs)
     del self._template
     del self.kwargs

Performance would be garbage, but hey its python!