Why are my object's assigned variables tuples? - python

I'm trying to first create an empty object and then assign variables to it with values. However, when I print the object variables, I discover they are of type tuple. Why aren't they just of type str or int for example?
I'm fairly new to Python so I might be missing something obvious to some.
Code that creates the object:
def getDbPoolConfig(self):
settingName = "pool"
dbConfig = EmptyObject()
dbConfig.host = settings.DATABASES[settingName]["HOST"],
dbConfig.port = settings.DATABASES[settingName]["PORT"],
dbConfig.user = settings.DATABASES[settingName]["USER"],
dbConfig.password = settings.DATABASES[settingName]["PASSWORD"],
dbConfig.dbName = settings.DATABASES[settingName]["NAME"]
return dbConfig
Code that uses the object and prints the object variables:
def dbConnect(self):
dbConfig = self.getDbPoolConfig()
print(dbConfig.host)
print(dbConfig.port)
print(type(dbConfig.port))
dbConnection = psycopg2.connect(user=dbConfig.user, password=dbConfig.password, dbname=dbConfig.dbName, host=dbConfig.host,port=dbConfig.port)
return dbConnection
Class:
class EmptyObject():
pass
Printed result:
('172.16.18.2',)
('5432',)
<class 'tuple'>
invalid port number: "('5432'"
invalid port number: ")"

dbConfig.host = settings.DATABASES[settingName]["HOST"],
dbConfig.port = settings.DATABASES[settingName]["PORT"],
dbConfig.user = settings.DATABASES[settingName]["USER"],
dbConfig.password = settings.DATABASES[settingName]["PASSWORD"],
Take out those commas at the end. That's the cause.

Turns out I didn't remove the commas when assigning the object variables. Remove the commas like this and it will work as expected:
def getDbPoolConfig(self):
settingName = "pool"
dbConfig = EmptyObject()
dbConfig.host = settings.DATABASES[settingName]["HOST"] # Removed commas here
dbConfig.port = settings.DATABASES[settingName]["PORT"]
dbConfig.user = settings.DATABASES[settingName]["USER"]
dbConfig.password = settings.DATABASES[settingName]["PASSWORD"]
dbConfig.dbName = settings.DATABASES[settingName]["NAME"]
return dbConfig

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

How to more quickly make a bunch of objects in Python

w_rook_1 = ChessPiece('w_rook_1')
w_knight_1 = ChessPiece('w_knight_1')
w_bishop_1 = ChessPiece('w_bishop_1')
w_king = ChessPiece('w_king')
w_queen = ChessPiece('w_queen')
w_bishop_2 = ChessPiece('w_bishop_2')
w_knight_2 = ChessPiece('w_knight_2')
w_rook_2 = ChessPiece('w_rook_2')
w_pawn_1 = ChessPiece('w_pawn_1')
w_pawn_2 = ChessPiece('w_pawn_2')
w_pawn_3 = ChessPiece('w_pawn_3')
w_pawn_4 = ChessPiece('w_pawn_4')
w_pawn_5 = ChessPiece('w_pawn_5')
w_pawn_6 = ChessPiece('w_pawn_6')
w_pawn_7 = ChessPiece('w_pawn_7')
w_pawn_8 = ChessPiece('w_pawn_8')
Is there an easier way to do this? I would also like to be able to use the objects afterwards.
Here is a simple approach using a dictionary when dealing with this type of challenge.
I added some comments within the code, please read.
instance_names = ['w_rook_1',
'w_knight_1',
'w_bishop_1',
'w_king',
'w_queen',
'w_bishop_2',
'w_knight_2',
'w_knight_2']
class ChessPiece(object):
def __init__(self, name):
self.name = name
self.move = "moving {}".format(name)
chess_objs = {}
for obj in instance_names:
# insert instance names ex. 'w_rook_1' as the key
# the ChessPiece instance is set as the value
chess_objs.setdefault(obj, ChessPiece(obj))
# here just illustrates how to access fields
# bound to each object
print(chess_objs['w_bishop_1'].name)
print(chess_objs['w_bishop_1'].move)
outputs:
w_bishop_1
moving w_bishop_1
If you follow #kaya3's advice and redesign your ChessPiece class, you could use a list comprehension easily, something like this (using abbreviations and ignoring number):
color = 'W'
non_pawns = [ChessPiece(color, c) for c in 'RNBKQBNR']
pawns = [ChessPiece(color, 'P') for _ in range(8)]

Adding a new object to a class with user-input(input) in python

I am trying to add new objects to a class(emne) but the new instances of the class needs to be created using user input. So i need a way to be able to chose the name for the object and set some of the values of the objects with user input.
I have already tried to create a function that passes the value of the user input into a x = emner(x) to create it but it only returns:
AttributeError: 'str' object has no attribute 'fagKode'
so i think my issue is that the value of the input is created as a string so that it is not understood as a way to create the function
emne=[]
class Emne:
def __init__(self,fagKode):
self.fagKode = fagKode
self.karakter = ""
emne.append(self)
def leggTilEmne():
nyttEmne = input("test:")
nyttEmne=Emne(nyttEmne)
expected result is that the code creates a new instance of the class.
If by choosing a name you mean your fagKode attribute, what you need is:
fagKode = input('Enter code: ')
Emne(fagKode)
You're adding the instances of Enme to the list in the constructor, so you don't need to save them to a variable.
Alternatively, you can handle that in the function:
emne=[]
class Emne:
def __init__(self,fagKode):
self.fagKode = fagKode
self.karakter = ""
def leggTilEmne():
nyttEmne = input("test:")
enme.append(Emne(nyttEmne))
I'm not sure what exactly you are asking, since you haven't responded to the comments. So,
emne=[]
class Emne:
def __init__(self,fagKode):
self.fagKode = fagKode
self.karakter = ""
emne.append(self)
def leggTilEmne(self, value): # <--- is this what you want
self.nyttEmne= Emne(value)
This is an example of when to use a class method. __init__ should not be appending to a global variable, though. Either 1) have the class method append to a class attribute, or 2) have it return the object and let the caller maintain a global list.
emne = []
class Emne:
emne = []
def __init__(self, fag_kode):
self.fag_kode = fag_kode
self.karakter = ""
#classmethod
def legg_til_emne_1(cls):
nytt_emne = input("test:")
cls.emne.append(cls(nytt_emne))
#classmethod
def legg_til_emne_2(cls):
nyttEmne = input("test:")
return cls(nyttEmne)
Emne.legg_til_emne_1() # Add to Emne.emne
e = Emne.legg_til_emne_2()
emne.append(e)

Why does this print the memory location of an object rather than what I want?

I'm not sure what's happening when I print my dictionary.
In Python 3, I have a dictionary of parse_blast objects called transSwiss. Each object's proteinID is the key with the entire object as the value.
I can print transSwiss in it's entirety and I can also print blasto.protein, but not when I combine them to get a dictionary value. I'm not sure what is happening when I use:
print(transSwiss[blasto.protein])
<__main__.parse_blast object at 0x000000373C5666A0>
Here is the code
class parse_blast(object):
def __init__(self, line):
#Strip end-of-line and split on tabs
self.fields = line.strip("\n").split("\t")
self.transcriptId, self.isoform = self.fields[0].split("|")
self.swissStuff = self.fields[1].split("|")
self.swissProtId = self.swissStuff[3]
self.percentId = self.fields[2]
def filterblast(self):
return float(self.percentId) > 95
class parse_matrix(object):
#Consider __init__ as a Constructor
def __init__(self, matrix_lines):
(self.protein,
self.Sp_ds,
self.Sp_hs,
self.Sp_log,
self.Sp_plat) = matrix_lines.strip("\n").split("\t")
def separate_tuples(one_tuple):
return "\t".join(one_tuple)
blastmap = map(parse_blast, blast_output.readlines())
filtered = filter(parse_blast.filterblast, blastmap)
matrixmap = map(parse_matrix, matrix_output.readlines()[1:])
transSwiss = {blasto.transcriptId:blasto for blasto in filtered}
for matrixo in matrixmap:
print(transSwiss[matrixo.protein])
Because your object is defined by you, you also need to tell python how you want it to print. You can do this by defining a function called "__str__" that returns how you want to print your object.
https://en.wikibooks.org/wiki/Python_Programming/Classes#str

How to grab variable from an import module

I am trying to get the variable - clipFileInfo in which it came from an import module. I run the following code:
from Library import libmaya
publishClip = libmaya.ClipPublish()
clip = publishClip.getClip()
print clip.clipFileInfo
But it will give me an error saying that # AttributeError: 'list' object has no attribute 'clipFileInfo' #
This is the portion of code that I am deriving from
class ClipPublish( lib.ClipPublish ):
...
...
def __getclipFileInfo( self ):
'''
Return list of dicts to pass through to writeClip function
'''
clipFileInfo = []
for rig in self.rigList.Rigs():
actor = rig.pop( 'actor', None )
if actor:
clipFileInfo = {}
clipFileInfo['actor'] = actor
clipFileInfo['rig'] = rig
clipFileInfo['name'] = self.__unit.get( rig['name'] )
clipFileInfo.append( clipFileInfo )
return clipFileInfo
def getClip( self ):
clipFileInfo = self.__getclipFileInfo()
if clipFileInfo:
start = self.frameRange.startFrame()
end = self.frameRange.endFrame()
clipFile = writeC.writeclip( clipFileInfo, start, end )
if clipFile == None:
return None
return clipFile[0] if self.isSingle() else clipFile
return []
Is this possible to do so in the first place?
It looks like you are trying to pull a local variable out of a function. Unless the function returns this local variable, it is not possible.
Instead, as the comment says, you should call publishClip.__getclipFileInfo() to get the value of that variable, since that function does return it.
To be more explicit, try the following code.
from Library import libmaya
publishClip = libmaya.ClipPublish()
info = publishClip.__getclipFileInfo()
print info

Categories

Resources