4

I looked at a similar question but it does not really answer the question that I have. Say I have the following code (overly simplified to highlight only my question).

class A:
    def __init__(self,x):
        self.val = x

a = A(4)
print a.val

This code resides in a file someones_class.py. I now want to import and use class A in my program without modifying someones_class.py. If I do from someones_class import A, python would still execute the script lines in the file.

Question: Is there a way to just import class A without the last two lines getting executed?

I know about if __name__ == '__main__' thing but I do not have the option of modifying someones_class.py file as it is obtained only after my program starts executing.

Community
  • 1
  • 1
Nik
  • 5,515
  • 14
  • 49
  • 75
  • 1
    If the module you want to import has lines like that in it that are not part of `if __name__ == '__main__':` suite, then it's broken and you shouldn't encourage the author by trying to work around it. Instead flag it as a bug to be fixed. – martineau Apr 23 '13 at 19:14

3 Answers3

8

This answer is just to demonstrate that it can be done, but would obviously need a better solution to ensure you are including the class(es) you want to include.

>>> code = ast.parse(open("someones_class.py").read())
>>> code.body.pop(1)
<_ast.Assign object at 0x108c82450>
>>> code.body.pop(1)
<_ast.Print object at 0x108c82590>
>>> eval(compile(code, '', 'exec'))
>>> test = A(4)
>>> test
<__main__.A instance at 0x108c7df80>

You could inspect the code body for the elements you want to include and remove the rest.

NOTE: This is a giant hack.

sberry
  • 128,281
  • 18
  • 138
  • 165
  • Thanks for the hack! Would it be possible to explain the code above? What do pop statements do? and the eval? – Nik Apr 23 '13 at 21:35
  • @Nik body is just a list of ast nodes, so pop removes the top node. eval will run the code as if the nodes that were popped were never part of the code – Catskul Apr 27 '19 at 07:47
2

Nope, there's no way to prevent those extra lines from being executed. The best you can do is read the script and parse out the class -- using that to create the class you want.

This is likely way more work than you want to do, but, for the strong willed, the ast module might be helpful.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • I was actually a little disappointed when `from module import class` did not work. I was hoping that since I specified exactly what it is I want to import, Python interpreter would understand that it does not need to deal with other stuff in the module. – Nik Apr 23 '13 at 19:18
  • 1
    @Nik -- There's a very good reason for that. `class` could use other constants, functions, classes defined at the module level. If python refused to import those as well, then the class you imported might not work – mgilson Apr 23 '13 at 19:19
2

No, there's no way. At least not without extreme trickery... that is to say, pretty much everything is possible in Python if you are willing to hack some weird "solution".

Where does that "someones_class.py" come from? Why can't you change it? I mean, edit the file, not change it from your code. Can you tell the person who wrote it not to write sort-a test code at top level?

There's an interesting (and kinda important) lesson about Python hidden here: that "class A:" is not a declaration. It's actually code that the Python interpreter executes when loading the file.

Jürgen A. Erhard
  • 4,908
  • 2
  • 23
  • 25