Error running script file with absolute path

Hi forum,

I get errors when I try running script with absolute path like this:
$ python /home/someone/someapp/myapp.py

But the following without path is fine:
$ cd /home/someone/someapp/
$ python myapp.py

The code uses logging with f-string and format().
f-string and format() cause different errors.

Thanks

# test:

$ pwd
/Users/ljh/Documents/helloPy
$ ls
appdir	libdir	log
$ 
$ find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
.
|____appdir
| |____myapp.py
|____log
| |____myapp.log
$ 
$

1. ok, with f-string # line 10
$ cd /Users/ljh/Documents/helloPy/appdir && python3 ./myapp.py

2. error, with f-string
$ python /Users/ljh/Documents/helloPy/appdir/myapp.py         
  File "/Users/ljh/Documents/helloPy/appdir/myapp.py", line 13
    logging.info(f'{__name__}')
                             ^
SyntaxError: invalid syntax
$ 

3. ok, with format() # line 11
$ cd /Users/ljh/Documents/helloPy/appdir && python3 ./myapp.py

4. error, with format(): logging to stdout, not to log file
$ python /Users/ljh/Documents/helloPy/appdir/myapp.py         
2022-03-03 13:29:37,669 INFO /Users/ljh/Documents/helloPy/appdir/myapp.py:14:logConfig: __main__
$

# myapp.py:

import sys
import logging
from logging.handlers import RotatingFileHandler

def logConfig():
    logging.basicConfig(
        # handlers=[RotatingFileHandler('../log/myapp.log', maxBytes=10*1024*1024, backupCount=10)],
        handlers=[RotatingFileHandler('/Users/ljh/Documents/helloPy/log/myapp.log', maxBytes=10*1024*1024, backupCount=10)],
        level=logging.DEBUG,
        format="%(asctime)s %(levelname)s %(pathname)s:%(lineno)d:%(funcName)s: %(message)s")
    # logging.info(f'{__name__}')       # line 10, Error, f-string
    logging.info('{}'.format(__name__)) # line 11, Error, .format()

def main():
    logConfig()

if __name__ == '__main__':
    main()

Thanks for copying and pasting the actual commands you entered, rather than just describing what you did.

It looks like you’re sometimes calling python, and sometimes calling python3.

python is probably Python 2.7, which is a very old version which is no longer supported and is missing many features. Make sure you only use python3, and you should be fine.

1 Like

Thanks Thomas,

My computer does have python 2 and 3. When I use python3 according to your help, it works!

Thank you for your time and patient for pointing this out.

not python v3

$ python /Users/ljh/Documents/helloPy/appdir/myapp.py
File “/Users/ljh/Documents/helloPy/appdir/myapp.py”, line 13
logging.info(f’{name}’)
^
SyntaxError: invalid syntax
$

ok, with python3

$ python3 /Users/ljh/Documents/helloPy/appdir/myapp.py
$

What’s happening, at least in your indicated example, is that Python 2 does not support the modern f-string syntax, which naturally results in a SyntaxError. As you discovered, running it with Python 3 solves this issue.

To note, its generally considered a best practice to let logging itself handle the formatting, using printf-style % placeholders in the string, and passing the variable data as positional parameters. This avoids building the logging message string except when it is actually needed, which improves performance, reduces the potential for bugs and doesn’t raise any errors doing so unless the logging message is actually emitted.

1 Like

Hi,

Why printf style improves performance? Programmer specifies type format in printf, so the Python interpreter can do less? The online tutorial (1) states that the printf style is old (obsolete?).

Mismatch format and value in printf in C causes undefined behavior. Python checks this kind of mismatch.

name = 'snake'
age = '3'  # value is in str type, not int type
print('name: %s, age: %d' % (name, age))  # TypeError
print(f'name: {name}, age: {age}')

1: 7. Input and Output — Python 3.10.2 documentation

I’m not suggesting using the % operator for formatting, but rather using logging's own string interpolation (which still uses the old printf-style placeholders for backward compatibility reasons, unless you use one of the various workarounds). See, e.g. the basic logging tutorial for more information. As I explained above, this (among other things) improves performance by only performing the string interpolation if the logging message is actually fired (e.g. lots of DEBUG log messages in a tight loop don’t impose a significant performance penalty on your application).

EDIT: At least in this case, there’s no need for using anything but %s or %r here, which work with any Python object; other types are only required for specialized type-specific formatting. So in general, you’ll only run into these sorts of issues if there’s an actual logic bug in your code, rather than simply a non-matching type that could reasonably be handled.

FYI, there’s no need for this legacy style formatting reminiscent of old text-only mailing lists in Discuss; like on most modern online platforms, you can simply use a normal inline link with Markdown, BBCode or HTML.

Thank you, sir,

I think I get it now.

You are trying to teach me using this log variable data instead of the other three kind of style.

name = 'snake'
age = 3

logging.info('name: %s, age: %d', name, age)  # log variable data

logging.info('name: %s, age: %d' % (name, age))  # printf-style
logging.info('name: {}, age: {}'.format(name, age))  # .format()
logging.info(f'name: {name}, age: {age}')  # f-string

Yup, exactly. To be more specific, you’re using the logger’s internal string interpolation rather than pre-interpolating the string then passing it to the logger, as the other methods all do. That way, the string only gets interpolated if the message is actually logged, rather than always, which is generally more efficient.

1 Like