3

Basically, I'd like to force a variable, lets call him jim into a plugin I load as a global, before the plugin loads, for instance:

load_plugin('blah', variables={'jim':1}) #For instance

And then inside blah.py:

print jim #prints 1

Is there any easy way to do this? Not a big deal if its not in the standard library.

  • The duplicate actually has a correct answer. Never thought anyone else would try to do this :) – Mad Physicist Nov 16 '18 at 14:20
  • The accepted answer there won't work if the module does have a `jim = None` line. The `None` value would be override any value set in the two-phase loading, suggested in that answer. And if the line is not there, any attempt to use the `jim` variable in the module body would show up as an error for linter tools (it would still work in runtime as described, though) – jsbueno Dec 18 '20 at 14:04

2 Answers2

2

No - there is no way to do that before the plug-in is imported in first place - so, if your variable is used in the module body itself, you are out of luck.

If the variable is used as a global variable inside the module's functions or methods (but not class bodies), you can change it after the module is imported simply doing:

import module
module.jim = 5

as you probably know. (And I am aware this is not what you are asking for).

So, the only way to achieve that would be to parse the source code for the module, and change the variable assignment there, save the source code and import it. Ok, there are ways to emulate importing with the source code in memory, but this approach is so impratical, we should not detail it.

If you have control over the source of the module you want to monkey-patch this way, my suggestion would be to use a configuration file from which the module would pick the variable names.

Then you generate the configuration file, perform the importing (taking care that it is not already imported into sys.modules) and you are done.

jsbueno
  • 99,910
  • 10
  • 151
  • 209
-1

You could use the __import__ function. It lets you override the globals.
for instance:

__import__('blah', dict(jim=1, **globals()))
Oren S
  • 1,820
  • 1
  • 19
  • 33
  • This doesn't seem to work, although it really looks like it should. I still get `NameError: name 'jim' is not defined.` – jozxyqk Mar 05 '16 at 12:55
  • 3
    The standard [`__import__] implementation [...] uses its globals only to determine the package context of the import statement. https://docs.python.org/2/library/functions.html#__import__ - this answers, despite being accepted and upvoted is plain wrong. – jsbueno Mar 05 '16 at 16:20
  • I'm with @jsbueno, this is the accepted answer but it does not work. – Shmuel Kamensky Dec 18 '20 at 13:55