Dynamic variable name in python - python

I'd like to call a query with a field name filter that I wont know before run time... Not sure how to construct the variable name ...Or maybe I am tired.
field_name = funct()
locations = Locations.objects.filter(field_name__lte=arg1)
where if funct() returns name would equal to
locations = Locations.objects.filter(name__lte=arg1)
Not sure how to do that ...

You can create a dictionary, set the parameters and pass this to the function by unpacking the dictionary as keyword arguments:
field_name = funct()
params = {field_name + '__lte': arg1, # field_name should still contain string
'some_other_field_name': arg2}
locations = Locations.objects.filter(**params)
# is the same as (assuming field_name = 'some_name'):
# Locations.objects.filter(some_name__lte=arg1, some_other_field_name=arg2)

Related

Python OPC UA pass variables to uamethod

I have an example where a method is being added to the server space. The example is set up to take two input values and add them together.
Code example
from opcua import Server, ua, uamethod, instantiate
import time
from opcua.ua import NodeId, NodeIdType
#uamethod
def add_func(self, a, b):
print("Adding parameters:\n", a, "\tand\t", b)
return a + b
if __name__ == "__main__":
# setup server
server = Server()
server.set_endpoint("opc.tcp://localhost:4840") #alternative:
server.set_endpoint("opc.tcp://0.0.0.0:4840")
server.set_server_name("Server example")
server.set_security_policy([ua.SecurityPolicyType.NoSecurity])
uri = "http://example.uri.de"
idx = server.register_namespace(uri)
# get Objects node, this is where we should adress our custom stuff to
objects = server.get_objects_node() # alternative: root_node = server.get_root_node()
# add structure to the namespace (idx) below the Objects node
myobj = objects.add_object(idx, "MyObject")
# add variables, type can be defined by assigning a value or ua Variant Type definition
var1 = myobj.add_variable(idx, "var1", 321, ua.VariantType.Int64)
var2 = myobj.add_variable(idx, "var2", 123, ua.VariantType.Int64)
# set variables writable for clients (e.g. UaExpert)
var1.set_writable()
var2.set_writable()
# set input arguments for method
input_arg1 = ua.Argument() # create new argument
input_arg1.Name = "a" # name for argument
input_arg1.DataType = ua.NodeId(ua.ObjectIds.Int64) # data type
input_arg1.ValueRank = -1 # value rank to be treated a scalar number
input_arg1.Description = ua.LocalizedText("First integer a") # add description text
input_arg2 = ua.Argument()
input_arg2.Name = "b"
input_arg2.DataType = ua.NodeId(ua.ObjectIds.Int64)
input_arg2.ValueRank = -1
input_arg2.Description = ua.LocalizedText("Second integer b")
# set output arguments
output_arg = ua.Argument()
output_arg.Name = "Result"
output_arg.DataType = ua.NodeId(ua.ObjectIds.Int64)
output_arg.ValueRank = -1
output_arg.Description = ua.LocalizedText("Sum")
print(var1.nodeid)
print(var2.nodeid)
# add method to namespace
mymethod = myobj.add_method(idx, "MyAddFunction", add_func, [input_arg1, input_arg2], [output_arg])
server.start()
The change I want to make is to remove the input arguments and automatically take var1 & var2 as input when calling MyAddFunction.
I use UaExpert to call this method.
UaExpert when calling MyAddFunction
I've tried to pass the variables by using their NodeID like this:
mymethod = myobj.add_method(idx, "MyAddFunction", add_func, [var1.nodeid, var1.nodeid], [output_arg])
and get following error message:
opcua.ua.uaerrors._base.UaError: NodeId: Could not guess type of NodeId, set NodeIdType
Is the type not defined when creating the variables?
What changes have to made for the method to take var1 & var2 as input argument? is there a way to assign these values to the created input arguments (input_arg1 & input_arg2)?
Thank you in advance!
regards Nando

TypeError: Error while checking if the values in a list existed in a dict

I have a code as follows:
class SifFile():
setting = {}
interesting_param = ['Temp', 'Pressure']
def __init__(self, get_param):
self.File_Type = "Andor Technology Multi-Channel File"
for k, v in get_param.items():
if SifFile.interesting_param in k:
SifFile.setting[k] = v
return SifFile.setting
get_parameter = {'Temp':75, 'Pressure':50, 'Helium':90, 'Exp':96}
sif = SifFile(get_parameter)
There is a big dict named get_parameter that has a few parameters and their values.
There is also a list named interesting_param that contains 2 elements.
What I want to do is to check which parameters from interesting_param list are present in the get_parameter dictionary and I want to save those parameters in an empty dict named setting
I tried running the above code, but it gives me the following error:
Traceback (most recent call last):
File "", line 16, in
sif = SifFile(get_parameter)
File "", line 8, in init
if SifFile.interesting_param in k:
TypeError: 'in ' requires string as left operand, not list
Expected output:
setting = {'Temp':75, 'Pressure':50}
Here is the code that will give you the expected answer:
class SifFile():
setting = {}
interesting_param = ['Temp', 'Pressure']
def __init__(self):
self.File_Type = "Andor Technology Multi-Channel File"
return
def func(self, get_param):
for k, v in get_param.items():
if k in SifFile.interesting_param:
SifFile.setting[k] = v
return SifFile.setting
get_parameter = {'Temp':75, 'Pressure':50, 'Helium':90, 'Exp':96}
sif = SifFile()
x=sif.func(get_parameter)
print(x)
I have created anothter funcion called "func" because "init()" cannot return a dictionary. It should only return "None".
Besides that, the condition statement within the for loop is changed.
The error is telling you what's wrong: you are trying to check if a key exists in a dict but the key that you're checking for isn't a string. Let's look at the line in question:
if SifFile.interesting_param in k:
The error thinks that SifFile.interesting_param is a list, so let's have a look at where you define that:
interesting_param = ['Temp', 'Pressure']
Oh yeah, that is a list. Since a list can't be a dict key it throws an error.
You need to loop through your items in interesting_param one by one to check whether they're in the dict. I've implemented that here, along with a range of other issues in your code, mainly surrounding how you'd implemented the class:
class SifFile():
"""
Class for holding and processing sif files.
"""
def __init__(self, params):
"""
Define the variables you want to use in your class
"""
self.file_type = "Andor Technology Multi-Channel File"
self.interesting_params = ['Temp', 'Pressure']
self.given_params = params
self.setting = {}
def get_settings(self):
"""
Return list of settings of interest
"""
# Look at every parameter of interest in turn
for param in self.interesting_params:
# Check to see if it is in the dict of given parameters
if param in self.given_params:
# If it is then add it to the setting dict
self.setting[param] = self.given_params[param]
# Return the setting dict once the loop is done
return self.setting
parameters = {'Temp':75, 'Pressure':50, 'Helium':90, 'Exp':96}
sif = SifFile(parameters)
print(sif.get_settings())
Note that your variables are now all instance variables rather than class variables (they start with self) because you're changing them, so they are unlikely to be the same for every class.

Where do I assign a variable in order for it to be used in a function (inside a class)?

I'm creating a class using tkinter that lets you input multiple product's information, and I've got everything else down except for changing the entry fields to set values for the other products.
I'm putting the product changeover process into a function called saveVars which saves the entered information to the specific product variable, and then clears the entry fields, and switches the saveVars to be performed on the second product variable.
i = 1
def saveVars(i):
if i == 1:
product1.productName = self.prodName.get()
product1.productID = self.prodID.get()
product1.productSize = self.prodSize.get()
product1.productPrice = self.prodPrice.get()
product1.productQuant = self.quantity.get()
elif i == 2:
product2.productName = self.prodName.get()
product2.productName = self.prodID.get()
product2.productSize = self.prodSize.get()
product2.productPrice = self.prodPrice.get()
product2.productQuant = self.quantity.get()
elif i == 3:
product3.productName = self.prodName.get()
product3.productName = self.prodID.get()
product3.productSize = self.prodSize.get()
product3.productPrice = self.prodPrice.get()
product3.productQuant = self.quantity.get()
newProduct()
i += 1
return i
I'm expecting to get it to switch the variable the entries are being saved to to the next respective product based on a +1 function, I'm having it return the i function as the new i, which should then save the entries to the next variable in the process, but it keeps telling me that I'm 'missing 1 required positional argument: 'i'
You are trying to call the function without parameter as the command attribute does not take parameters just the name of the function.
To pass parameters you could use partial form functools package
import statement :
from functools import partial
your call to function would look like :
addItemButton = Button(window, text = "Add to Cart", fg='black',bg='yellow',width = 10, height = 2, command = partial(saveVars,i)) addItemButton.place(x=800,y=375)
You can set the inital value to i in your class using a global variable instead of declaring it outside the class. You can save it anywhere you wish and pass it while calling the funtion.
It seems like you are calling saveVars without the parameter in some case. To prevent this you can set a default value of i, eg.
def saveVars(i=0)

Pythonic way to check if a variable was passed as kwargs?

visible = models.BooleanField()
owner = models.ForeignKey(User, null=True)
def update_address(**kwargs):
address = Address.objects.get(address=kwargs.get('address'))
try:
address.visible = kwargs.get('visible')
except:
pass
try:
address.owner = kwargs.get('owner')
except:
pass
update_address() should result in nothing happening to address.visible or address.owner.
update_address(owner=None) should delete whatever existing owner object was set.
The thing that's confusing me is how to tell if owner=None was explicitly set so I know to delete the existing owner object, or if it was called without owner set to anything so I should leave the owner as it is.
you can use the "in" keyword to check if the key is there or you can specify the default param in the second argument of the dict.get(key, default) function
if 'visible' in kwargs:
do something
# OR
visible = kwargs.get('visible', False)
Update:
if your super() class (ie the parent model) doesn't take the visible param, you can use the dict.pop(key, default) to extract the param before passing it to the super. I thought this could be useful for you to know as well.
def __init__(self, *args, **kwargs):
visible = kwargs.pop('visible', False)
super().__init__(*args, **kwargs)
You could use in and keys:
if 'visible' in kwargs.keys():
...
You can also make your own default option, if that is more convenient; by making an instance of object you can ensure it's distinct from anything else
no_parm = object() # this object is only used for default parms
def thisfunc( p = no_parm ):
if p is no_parm:
# default was used
def thatfunc(**kwargs):
rateval = kwargs.get('rate', no_parm)
if rateval is not no_parm:
# it could be None, if the functiion wa called
# as thatfunc( rate=None)
#
...
Note the use of is for comparisons - this is possible - and recommended - since we are checking if we have two references to exactly the same object - and not a value equality as == does.

Dynamic keyword with database value

I have a model like this:
class meter1(models.Model):
U1N = models.FloatField(default=0)
U2N = models.FloatField(default=0)
In my view (simplified) I want to set the value for the database dynamically:
def import_data:
dict = {"1":"U1N","2":"U2N",}
c = "1"
q = meter1()
q.eval('dict[c]') = "1"
q.save()
In real dict contains 60 items, and c changes every time in a for loop. The code in this example results in an error: NameError: name 'U1N' is not defined.
How do I dynamically set the keyword for q?
You can also dynamically build a dict from your dict (you shouldn't use a builtin name as identifier BTW) and pass it as kwargs to meter1() (you shouldn't use all-lowers as class names BTW). Oh and yes: you may want to have a look at modelmanager.create() too.
def import_data():
fieldmap = {"1":"U1N","2":"U2N",}
fieldindex = "1"
kw = {fieldmap[fieldindex]: 1.0}
# either:
q = Meter1(**kw)
q.save()
# or:
q = Meter1.objects.create(**kw)
You can use setattr to dynamically set attributes to the objects.

Categories

Resources