Note: updated my original question
I have this code part in a script and need to access co_create value outside the module in the script.
from ansible.plugins.callback import CallbackBase
class CallbackModule(CallbackBase):
CALLBACK_VERSION = 2.0
def __init__(self):
super(CallbackModule, self).__init__()
def v2_playbook_on_play_start(self, play):
self.play = play
extra_vars = ""
vm = play.get_variable_manager()
co_create = vm.extra_vars["co_create"]
The way you have formatted print(co_create) on the final line in your snippet, it appears as the last line of the class definition for CallbackModule. When the class constructor get's to that point it is rightly complaining that the variable is not defined as there is neither a class-level variable in your example called co_create nor a reference to any global variable called co_create available at the module level. You have two options: (1.) define a module-level variable in the peer context to the class' definition, before the class is defined, called 'co_create' like:
co_create = None
class CallbackModule(CallbackBase):
...
if __name__ == '__main__':
play = ...
obj = CallbackModule()
obj.v2_playbook_on_play_start(play)
print(co_create) # no longer None
This will become the global variable you desire and should not require code change to any of your other code. (2.) similar to what you defined in the instance method v2_playbook_on_play_start access co_create with the global keyword at the class level before you print it. Option (1.) is preferred. You should try to avoid using global keyword unless you have to simply because it will require consistency across rest of module, hence more global keywords and more opportunities for error.
I got my answer: it's not possible what I originally wanted to achieve with the ansible module: to get the variable retrieved from the module into the main block in the script, because the 'play' is called directly from ansible run, so no way I can specify it in the main block.
So I did make it work to push the return value from the main block to the module and the module to do the task instead.
Since skullgoblet1089 gave me a good direction, I will mark his answer good.
Related
I have a code with a class using many variables.i can't Access one of those variables to use it inside of a method of my code written in Python.
I tried to declare the variable as global to make the value being accessible at any point of the code but it is not ok. I am expecting to use the variable in a specific method
In Python, "variables" are really "names" and you can access them whenever they're in scope!
However, if you intend to modify a name that's outside of the current scope, you need to tell the interpreter so (otherwise it'll assume that you mean to give the name to something else within your scope)
a = None
def foo():
# you can access a, but not set it here
print(a)
a = None
def foo():
a = 1 # a is only set within foo
print(a) # refers to a in outer scope
usage of global
a = None
def foo():
global a
# now you can modify a
a = 1
creates an error
a = None
def foo():
print(a)
global a # SyntaxError: name 'a' is used prior to global declaration
There is no easy way. Use (global a) when you are changing the variable in the function.
For example when you are changing the variable in a function.
a = 0
def asi():
global a
a = 1
Output : 1
For example when you are not changing the variable but want to use it in a function.
a = 0
def asi():
print(a)
Output : 0
your question is not clear to me:
you didn't share any code for interpretation
in OOP ( us said class and methods ) how could you not be able to access variable (global variable or class variable: both may not same but its for sake of argument)
by 'in my code written in python' what do you mean actually? with in same class? method? module? venv?
Note:- every question may not have answer in coding it may be literature... ( that whats logic is.....)
I've been playing with my codes a little for a while, and this one is not about a bug or anything, but i just don't understand why class main() runs without needing to initialize it...
class vars():
var1 = "Universe!"
var2 = "Oscar!"
var3 = "Rainbow!"
class main():
print (vars.var1)
def __init__(self):
print (vars.var2)
print (vars.var3)
But yes, thank you very much for reading.
Unlike many other languages, class body is an executable statement in Python and is executed immediately as the interpreter reaches the class line. When you run this "program":
class Foo:
print("hey")
it just prints "hey" without any Foo object being created.
The same applies to the function definition statement def (but not to function bodies). When you run this:
def foo(arg=print("hi")):
print("not yet")
it prints "hi", but not "not yet".
When a class is created, Python executes all of the code directly inside the class declaration in a new namespace. This is so that any variables created in the class (most commonly methods, created by ordinary function declarations like def foo(self...)) are attached to the class rather than being global.
But the code still runs immediately. If it calls print() or does something else which creates a visible side effect, that will happen now, not when the class is instantiated (called to create a new instance). If you need something to happen when the class is instantiated, write an __init__() method instead.
main is a class not a function. Thus the code contained in the class declaration runs immediately because all statements are executed as they appear in code. As a method declaration is reached, it's bound to the class as a member, so in a way methods execute as well but are not called.
When Python read your code, it looked into class vars and defined all the variables. Then, it went into class main and executed the code there, as well as defining init. Python just executes whatever which is not in a function definition.
What I am trying to do, is creating a module, with a class; and a function, which is an interface of that class; and a variable name on-the-fly in this function, which is pointing to an instance of that class. This function and the class itself should be in a separate module, and their usage should be in a different python file.
I think, it's much easier to understand what I am trying to do, when you are looking at my code:
This is the first.py:
class FirstClass:
def setID(self, _id):
self.id = _id
def func(self):
pass
# An 'interface' for FirstClass
def fst(ID):
globals()['%s' % ID] = FirstClass(ID)
return globals()['%s' % ID]
Now, if I'm calling fst('some_text') right in first.py, the result is pretty much what I dreamed of, because later on, any time I write some_text.func(), it will call the func(), because some_text is pointing to an instance of FirstClass.
But, when the second.py is something like this:
from first import fst
fst('sample_name')
sample_name.func()
Then the answer from python is going to be like this:
NameError: name 'sample_name' is not defined.
Which is somewhat reasonable.. So my question is: is there a "prettier" method or a completely different one to do this? Or do I have to change something small in my code to get this done?
Thank you!
Don't set it as a global in the function. Instead, just return the new instance from the function and set the global to that return value:
def fst(ID):
return FirstClass(ID)
then in second.py:
sample_name = fst('sample_name')
where, if inside a function, you declare sample_name a global.
The globals() method only ever returns the globals of the module in which you call it. It'll never return the globals of whatever is calling the function. If you feel you need to have access to those globals, rethink your code, you rarely, if ever, need to alter the globals of whatever is calling your function.
If you are absolutely certain you need access to the caller globals, you need to start hacking with stack frames:
# retrieve caller globals
import sys
caller_globals = sys._getframe(1).f_globals
But, as the documentation of sys._getframe() states:
CPython implementation detail: This function should be used for internal and specialized purposes only. It is not guaranteed to exist in all implementations of Python.
Context: I'm making a Ren'py game. The value is Character(). Yes, I know this is a dumb idea outside of this context.
I need to create a variable from an input string inside of a class that exists outside of the class' scope:
class Test:
def __init__(self):
self.dict = {} # used elsewhere to give the inputs for the function below.
def create_global_var(self, variable, value):
# the equivalent of exec("global {0}; {0} = {1}".format(str(variable), str(value)))
# other functions in the class that require this.
Test().create_global_var("abc", "123") # hence abc = 123
I have tried vars()[], globals()[variable] = value, etc, and they simply do not work (they don't even define anything) Edit: this was my problem.
I know that the following would work equally as well, but I want the variables in the correct scope:
setattr(self.__class__, variable, value) # d.abc = 123, now. but incorrect scope.
How can I create a variable in the global scope from within a class, using a string as the variable name, without using attributes or exec in python?
And yes, i'll be sanity checking.
First things first: what we call the "global" scope in Python is actually the "module" scope
(on the good side, it diminishes the "evils" of using global vars).
Then, for creating a global var dynamically, although I still can't see why that would
be better than using a module-level dictionary, just do:
globals()[variable] = value
This creates a variable in the current module. If you need to create a module variable on the module from which the method was called, you can peek at the globals dictionary from the caller frame using:
from inspect import currentframe
currentframe(1).f_globals[variable] = name
Now, the this seems especially useless since you may create a variable with a dynamic name, but you can't access it dynamically (unless using the globals dictionary again)
Even in your test example, you create the "abc" variable passing the method a string, but then you have to access it by using a hardcoded "abc" - the language itself is designed to discourage this (hence the difference to Javascript, where array indexes and object attributes are interchangeable, while in Python you have distinct Mapping objects)
My suggestion is that you use a module-level explicit dictionary and create all your
dynamic variables as key/value pairs there:
names = {}
class Test(object):
def __init__(self):
self.dict = {} # used elsewhere to give the inputs for the function below.
def create_global_var(self, variable, value):
names[variable] = value
(on a side note, in Python 2 always inherit your classes from "object")
You can use setattr(__builtins__, 'abc', '123') for this.
Do mind you that this is most likely a design problem and you should rethink the design.
Both of these blocks of code work. Is there a "right" way to do this?
class Stuff:
def __init__(self, x = 0):
global globx
globx = x
def inc(self):
return globx + 1
myStuff = Stuff(3)
print myStuff.inc()
Prints "4"
class Stuff:
def __init__(self, x = 0):
self.x = x
def inc(self):
return self.x + 1
myStuff = Stuff(3)
print myStuff.inc()
Also prints "4"
I'm a noob, and I'm working with a lot of variables in a class. Started wondering why I was putting "self." in front of everything in sight.
Thanks for your help!
You should use the second way, then every instance has a separate x
If you use a global variable then you may find you get surprising results when you have more than one instance of Stuff as changing the value of one will affect all the others.
It's normal to have explicit self's all over your Python code. If you try tricks to avoid that you will be making your code difficult to read for other Python programmers (and potentially introducing extra bugs)
There are 2 ways for "class scope variables". One is to use self, this is called instance variable, each instance of a class has its own copy of instance variables; another one is to define variables in the class definition, this could be achieved by:
class Stuff:
globx = 0
def __init__(self, x = 0):
Stuff.globx = x
...
This is called class attribute, which could be accessed directly by Stuff.globx, and owned by the class, not the instances of the class, just like the static variables in Java.
you should never use global statement for a "class scope variable", because it is not. A variable declared as global is in the global scope, e.g. the namespace of the module in which the class is defined.
namespace and related concept is introduced in the Python tutorial here.
Those are very different semantically. self. means it's an instance variable, i.e. each instance has its own. This is propably the most common kind, but not the only one. And then there are class variables, defined at class level (and therefore by the time the class definition is executed) and accessable in class methods. The equivalent to most uses of static methods, and most propably what you want when you need to share stuff between instances (this is perfectly valid, although not automatically teh one and only way for a given problem). You propably want one of those, depending on what you're doing. Really, we can't read your mind and tell you which one fits your problem.
Globals variables are a different story. They're, well, global - everyone has the same one. This is almost never a good idea (for reasons explained on many occasions), but if you're just writing a quick and dirty script and need share something between several places, they can be acceptable.