3

I see one python script start with

#!%{__python34}

from __future__ import unicode_literals
# Whether we're Python 2

I guess __python34 is used to get the path of python2 or python 3.4, but it does not seem work, as the output message says that the file does not exist...

Thanks.

dlz
  • 141
  • 7
  • 7
    I think that syntax is for a template variable (like [Jinja](http://jinja.pocoo.org)). So what happens is that you declare in a different file a variable like `__python34:/usr/bin/python3.4`, then run the templating engine on this script, and the output will be `#!/usr/bin/python3.4` [This thread](https://stackoverflow.com/questions/6908143/should-i-put-shebang-in-python-scripts-and-what-form-should-it-take) pretty much explains the use of the shebang in Python – Adonis Aug 02 '17 at 13:20

1 Answers1

2

I believe it is a technique known as "templating" (%{var} is used for instance in the template engine used by RPM as we can see in this example, see the .specfile especially). And a lot of these templating engine exists, Jinja2, Mako and so on and so forth (a more exhaustive list can be found here)

Now let's use Jinja2 to create a simple example, the first thing we create is a template (let's put it in a templates folder to follow the convention), let's call it, python_script_tmpl:

#!{{ python }}

def main():
    print("It works")

Now let's create an init (empty script) to create an environment to use with Jinja2.

Now you should have a structure like:

myapp/
  __init__.py
  templates/
    python_script_tmpl

Let's start a shell in the the my_app directory, and run the following line (doc to install jinja2):

from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader("__init__", "templates")) #use the blank __init__ script to init the environment, and the templates folder to load templates
tmpl = env.get_template("python_script_tmpl") #load the template 
tmpl.stream(python="/usr/bin/env python3").dump("python_script.py") #create from the template a script called python_script.py

And now at the root of my_app you should have the script python_script.py and it should look like:

#!/usr/bin/env python3

def main():
    print("It works")

With the final folder structure:

myapp/
  __init__.py
  python_script.py
  templates/
    python_script_tmpl

Assuming the shebang and the env is correctly configured you can run the script without an issue. (albeit not a pretty useful script)

Now what's the point of templating?

If you have to repeat parts a lot of time, (for example the shebang), and that you have to modify it, then you'd have to modify it for every file where it appears, if you use a template, you just have to modify the variable once and inject it. That's a straightforward advantage of templating.

P.S: As @CharlesDuffy mentions, this script is probably extracted from a RPM package, so except for learning purposes, or repackaging, I would suggest you use the rpm command line tool to run the whole package.

Adonis
  • 4,670
  • 3
  • 37
  • 57
  • 1
    `%{var}` is used by RPM's template engine. Presumably, then, this is supposed to be replaced at package build time. – Charles Duffy Aug 02 '17 at 14:43
  • @CharlesDuffy Very good point, I edited my post to reflect this. – Adonis Aug 02 '17 at 15:03
  • 1
    @CharlesDuffy and asettouf, Thanks for the answer and comments. The file is indeed from a package installed through RPM. If I understand corrected, it's not expected to show up in the installed files? i.e., I guess it should already be replaced with the correct shebang line during the installation managed by RPM? – dlz Aug 03 '17 at 10:32
  • @dlz Correct, assuming all requirements are satisfied for the installation of the RPM, a correct shebang should indeed be present in this file after installation. – Adonis Aug 03 '17 at 10:38
  • @dlz, I'd suggest filing a bug report with the distro/repo/&c. you got the package from. – Charles Duffy Aug 03 '17 at 14:57