-2

I have a config.yaml which contains following:

SQL1: 'select * from {x1}'
SQL2: 'select * from {x2}'
SQL3: 'select * from {x3}'
SQL4: 'select * from {x2}'
SQL5: 'select * from {x1}'

Then I have my script (example):

x1 = 'test'
x2 = 'test2'
x3 = 'test3'

for sql in ['SQL1', 'SQL2', 'SQL3', 'SQL4', 'SQL5']:
    print(config[sql])

Desired output:

select * from test
select * from test2
select * from test3
select * from test2
select * from test

But this doesn't work. I need to tell Python somehow that the string which config['SQL1'] points to is a formatted string like f''

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
chrisaramar
  • 271
  • 4
  • 10
  • 4
    Just use the regular `.format` method, e.g. `'Print my var: {x}'.format(x='foo')` -> `'Print my var: foo'` – jonrsharpe Mar 24 '22 at 14:52
  • Hi @jonrsharpe I edited my question a bit I think i was a bit missunderstanding at first now it should be clear. The .format function doesnt help here because it needs a var name from me which I dont know at this moment – chrisaramar Mar 24 '22 at 15:04
  • How are you going to set `x = 'This is my var'` if you don't know that `x` is what needs to be defined? – jonrsharpe Mar 24 '22 at 15:05
  • Ah it's a bit complex :D I know I have 5 vars. Then i iterate over 5 sqls and want to set the vars for each sql. But each sql needs other vars. You know what I mean? – chrisaramar Mar 24 '22 at 15:09
  • No. Please give a representative example. This sounds like a huge injection risk. – jonrsharpe Mar 24 '22 at 15:10
  • @jonrsharpe I hope now its understandable – chrisaramar Mar 24 '22 at 15:20
  • 2
    You can just pass _all_ the variables that should be made available, `.format(x1=x1, x2=x2, x3=x3)`. If it's a larger set, unpack a dictionary. – jonrsharpe Mar 24 '22 at 15:23
  • Well that seems to work because python just ignores not used variables. Didnt thought so thank you :) – chrisaramar Mar 24 '22 at 15:26
  • you can write it as an answer then I can mark it as the solution – chrisaramar Mar 24 '22 at 15:27
  • These options are already discussed in e.g. https://stackoverflow.com/q/42497625/3001761 – jonrsharpe Mar 24 '22 at 15:33

3 Answers3

1
KEY: 'Print my var: {x}'

You can do it easily if the brackets {} are empty, with the str method .format:

a = "Print my var: {}"
print(a.format(x))

You can achieve this using re (regex = REGular EXpression), and removing x from the string.


As I just read from documentation and from @jonrsharpe's comment, you can do it also passing x as a **kwarg of .format:

a = "Print my var: {x}"
print(a.format(x="Variable"))

If you don't know the name of the variable, you can estract it with regex as suggested above, remove it from the string leaving the {} empty, and then get its value this way:

print(a.format(globals()[variable_name_you_got_from_regex]))
FLAK-ZOSO
  • 3,873
  • 4
  • 8
  • 28
  • hi thanks but I need to fill the specific var "x" but i dont know that its called x. I will change my question a bit to get more specific :) – chrisaramar Mar 24 '22 at 14:58
  • changed the question maybe now its more understandable – chrisaramar Mar 24 '22 at 15:02
  • Ok, understood, in this case you will have to use regex... – FLAK-ZOSO Mar 24 '22 at 15:04
  • I dont think this will work for me either. I have some big sqls which i need to iterate over and where i have to fill vars. I dont want those sqls in my code which is why I moved it to a config. Each sql needs other vars which i am able to set before iterating but I wanted to make it dynamically. But if there is no way, i have to check which sql i called with an if and add the var based on which sql i have :( – chrisaramar Mar 24 '22 at 15:08
0

This might not scale, but based on your example and the current values this would work:

config = {
    "SQL1": "select * from {x1}",
    "SQL2": "select * from {x2}",
    "SQL3": "select * from {x3}",
    "SQL4": "select * from {x2}",
    "SQL5": "select * from {x1}",
}

x1 = "test"
x2 = "test2"
x3 = "test3"

for sql in ["SQL1", "SQL2", "SQL3", "SQL4", "SQL5"]:
    config_line = config[sql]
    config_line = config_line.replace('{x1}', x1)
    config_line = config_line.replace('{x2}', x2)
    config_line = config_line.replace('{x3}', x3)
    print(config_line)

The output is:

select * from test
select * from test2
select * from test3
select * from test2
select * from test

Another option is to use a template, modifying your input to match the template format.

from string import Template

config = {
    "SQL1": "select * from $x1",
    "SQL2": "select * from $x2",
    "SQL3": "select * from $x3",
    "SQL4": "select * from $x2",
    "SQL5": "select * from $x1",
}

replacement_mapping = {
    "x1": "test",
    "x2": "test2",
    "x3": "test3",
}
for sql in ["SQL1", "SQL2", "SQL3", "SQL4", "SQL5"]:
    config_line = config[sql]
    template = Template(config_line)
    print(template.substitute(**replacement_mapping))

Then you can pass a dictionary of the standin variables and their replacement values.

0

What works is to use

'Set {x}, {y} but not z'.format(x=x, y=y, z=z).

Python will just ignore not used vars like in this example 'z'.

chrisaramar
  • 271
  • 4
  • 10