0

I am trying to call a function that takes an object as an argument. The code looks somethin like this

exec(f"{object.attr1}.{object.attr2}({interface_obj})")

When I run this, I run into a

SyntaxError: invalid syntax

The syntax error is pointed right at the beginning of interface_obj But python does not say what exactly the issue is. Has anyone encountered this?

I had an issue with a dictionary converted to a class and circumvented by just passing the dictionary itself. However for the interface_obj I cannot do the same.

EDIT:

Here is some context - I am developing an automation platform that can run multiple tests. Each test is essentially an independent .py file.

for e.g.

main.py
.\Main_dependency
      |__ test_calling_script.py
.\Test
      |__ test1.py
      |__ test2.py
      :
      |__ testN.py

My idea is to have a single point of test import in the test_calling_script.py and run the respective test based on input. Hence using exec to have a single line code to call the corresponding test.

 test1.test_func(<__main__.TEST object at 0x000002962BF83FD0>)
                 ^
SyntaxError: invalid syntax

Thanks for the comments folks! I was able to use a combination of answers from @juanpa.arrivillaga and @cookieobjects to achieve what I was trying.

Updated Snippet

Usage
from importlib import import_module
variable = getattr(import_module(<package_name>.<test_file_name>, function)
variable(argument) 

Code
from importlib import import_module
test_module = getattr(import_module(f'Test.{object.attr1}'), {object.attr2})
test_module(interface_obj)

Found another question with similar use case

pedru
  • 13
  • 4
  • 2
    Leaving aside that you almost **certainly shouldn't be using `exec` here**, have you actually looked at what the ouput of `f"{object.attr1}.{object.attr2}({interface_obj})"` is? What is it? The syntax error will likely jump out at you then – juanpa.arrivillaga Jun 13 '23 at 22:58
  • Temporarily replace the `exec` by `print` to see (and show us) what `exec` actually receives. – Michael Butscher Jun 13 '23 at 22:59
  • 1
    In any case, you really must provide a [mcve]. Because, the line `exec(f"{object.attr1}.{object.attr2}({interface_obj})")` has no syntax error. The error is probably arising from the code you are dynamically executing, or possibly, it actually comes from a line before this one. – juanpa.arrivillaga Jun 13 '23 at 22:59
  • @juanpa.arrivillaga - Can you expand on why exec is a strict no-no here? In my code this is integral to have a flexible and scalable functionality. I have a work around which is using a bunch of if-else to implement what I was envisioning to achieve with exec – pedru Jun 14 '23 at 15:34
  • 1
    Because in general, dynamically creating strings to execute as code is a brittle approach, and although sometimes it's a reasonable solution, Python is a very dynamic language that often allows you much less brittle approaches to achieving whatever it is you are trying to achieve. that being said, you haven't actually described what it is you are trying to achieve! what exactly are your inputs here, and what are your expected outputs? – juanpa.arrivillaga Jun 14 '23 at 15:38
  • So, you still haven't really provided a [mcve]. But it *looks* like you just want something like `getattr(globals[obj.attr1], obj.attr2)(interface_obj)` – juanpa.arrivillaga Jun 15 '23 at 01:28

1 Answers1

0

Using exec() for external scripts is bad practice due to having few checks as to whether or not your script is valid, and due to the limited nature of error handling for such highly dynamic and broad-spectrum functionality. It is more difficult to diagnose without a little infrastructure describing what is actually going on.

For the problem of needing a way to dynamically import and run python scripts from an external folder, you can use importlib.

import importlib

def import_test(file_name):
    return importlib.import_module(file_name)

testing_module = import_test('testing_module')
results = testing_module.test_function(interface_obj)

Your "loader" function would be import_test, and would be "test_calling_script" in your folder structure.

  • Thanks for introducing me to importlib!! Your answer helped me solve the my problem with some modifications to the snipped you provided. – pedru Jun 20 '23 at 22:10