0

I am developing a Python package which does work by taking in user-defined objects all of which are instances of a class which I wrote. The way I have designed is, user passes his/her objects as defined in one or more python scripts (see example below).

I want to access the objects which user defines in the scripts. How can I do that?

I looked at import by filename but to no avail. I even went on to use imp.load_source but didn't solve.

Some typical user-defined objects

Assume for the sake of the problem, all methods are defined in Base. I understand what I am asking for leads to arbitrary code execution, so I am open to suggestions wherein users can pass their instances of the Base class arbitrarily but safely.

foo.py has the following code:

from package import Base
foo = Base('foo')
foo.AddBar('bar', 'bar')
foo.AddCow('moo')

ooo.py :

from package import Base
ooo = Base('ooo')
ooo.AddBar('ooo','ooo')
ooo.AddO(12)

And I run my main program as,

main_program -p foo.py ooo.py

I want to be able to access foo, ooo in the main_program body.

Tried:

I am using python2.7 I know I am using older Python, I will make the move soon

importlib

Tried importlib.import_module but it throws ImportError: Import by filename is not supported.

__import__

I tried using __import__('/path/to/file.py') but it throws the same ImportError: Import by filename is not supported.

At this point, any solution which lets me use objects defined in user-input scripts works.

Surya
  • 1
  • 1
  • Hi Surya, welcome to StackOverflow. Can you also give a note on the overall problem you are trying to solve so people can suggest a good solution? – S Raghav Apr 04 '19 at 02:59
  • 1
    do you mean `ooo = importlib.import_module("ooo")` ? – furas Apr 04 '19 at 03:02
  • @furas: I tried importlib, it throws `ImportError: Import by filename is not supported`. – Surya Apr 04 '19 at 03:05
  • @furas, apologies, I realized what you meant after I made by first comment. I haven't tried, so I don't know if it would work, and even if it does work, my `main_program` would **HAVE** to know the names of these `Base` class instantiations. I am not inclined to enforce that design constraint on the user. – Surya Apr 04 '19 at 03:16
  • @raghav710, Sure. I added some more text. Would that be enough? – Surya Apr 04 '19 at 03:17
  • @Surya thanks for the additional info. May I know why you would want the user to pass in the file names, instead of, say, the user passing a number/alphabet and you picking the class. Are the classes like plugins that can be loaded dynamically? – S Raghav Apr 04 '19 at 03:28

2 Answers2

0

If you are okay with skipping the .py in the filename, this can be solved by asking the user to pass the module name (basically the file name without the py) extension

Referring to this answer and this book, here is an example

tester.py

class A:
    def write(self):
        print("hello")

obj = A()

Now we want to dynamically access obj from a file called test.py, so we do

python test.py tester

And what does test.py do? It imports the module based on name and access it methods. Note that this assumes you are not concerned about the order in which the user passes the objects

test.py

import sys
# Get all parameters (sys.argv[0] is the file name so skipping that)
module_names = sys.argv[1:]
# I believe you can also do this using importlib
modules = list(map(__import__, module_names))
# modules[0] is now "tester"
modules[0].obj.write()

Mapping this to your example, I think this should be

foo.py

from package import Base
foo = Base('foo')
foo.AddBar('bar', 'bar')
foo.AddCow('moo')

ooo.py

from package import Base
ooo = Base('ooo')
ooo.AddBar('ooo','ooo')
ooo.AddO(12)

And run main program as

python main_program.py foo ooo
S Raghav
  • 1,386
  • 1
  • 16
  • 26
0

Have you tried

from (whatever the file name is) import *

Also don’t include .py in the file name.

  • `filename` is a variable, hence, I can't do this. – Surya Apr 04 '19 at 17:27
  • Maybe we aren’t on the same page here. You need to put the class or whatever you are trying to import into a separate file. That’s the only way to import something. You can name the file whatever you want it just needs to be in the same folder as your main program file. – Brandon Wegner Apr 07 '19 at 00:43