I have a variable, abc
, defined as 'batting_stats'
and want to run a line of code that is 'pyb.batting_stats(2020)'
. I want to use string syntax to create the line by joining abc with 'pyb.'
and '(2020)'
and then run that line of code - how can I do this? I seem to be creating a larger string instance rather than a runnable line of code. Cheers!
CodePudding user response:
You probably don't want to do this; it's possible, but in the vast majority of circumstances, it's a bad idea.
Options:
If possible, try to rewrite the code so you don't need to look up by name at all; for instance, you could change the other code so that it stores
pyb.batting_stats
as a function rather than as a stringabc = pyb.batting_stats # note no brackets # later result = abc(2020)
If you do need to look up by name, you can use
getattr
, like this:# At the top of the script ALLOWED_NAMES = ['batting_stats', ...] # in the code where you need it if abc not in ALLOWED_NAMES: raise ValueError("Invalid name passed: %s" % abc) result = getattr(pyb, abc)(2020)
Probably a better way would be to use a dictionary as a dispatch table:
dispatch_table = { 'batting_stats': pyb.batting_stats, ...: ..., } result = dispatch_table[abc](2020)
This automatically raises an exception if an unexpected name is passed.
It also has the benefit that you can use a different string in the
abc
variable than the method name; for example, if you need to rename the function but maintain the names in an API or vice versa:dispatch_table = { 'battingstats': pyb.batting_stats, # legacy name 'batting_stats': pyb.batting_stats, ...: ..., } result = dispatch_table[abc](2020)
If you absolutely must run a piece of code from a string, you can use the
eval
orexec
builtin functions; however, it's almost always a bad idea.Use of
eval
andexec
is so frequently dangerous and insecure (Common Weakness #95) that it's better to avoid it altogether. Luckily, at least in Python, there's almost always an alternative; moreover, those alternatives are typically cleaner, more flexible, faster to run and easier to debug. Cases where there's no alternative are vanishingly rare.
CodePudding user response:
There are two ways so get this answer.
First you can try something like
os.system(f'pyb.{abc}(2020)')
or
exec('print("hi")')
If you want to store the output try this