Python - Stopping on first IF condition - python

I am struggling to understand why my script only matches the first key in the dictionary and doesn't proceed to process other keys.
My script generates the command I need if say only tcp ports are present but if I try to mix this and have other ports(keys) it will not process the other elif. Whether I put this in a for loop or not I seem to be getting the same results. Im new to this so I might have missed something basic here.
ports = {'tcp': [['10', '20']], 'rant': [['100', '200']], 'cm': ['https']}
if __name__ == "__main__":
obj = []
tcpport = []
udpport = []
mxport = []
if ports.get("tcp"):
tcp2 = ports.get("tcp")
tcpport = True
for t in compile_port2(tcp2):
obj.append(t)
print("compiled tcp only objects")
elif ports.get("udp"):
udpport = True
udp2 = ports.get("udp")
for u in compile_port2(udp2):
obj.append(u)
print("compiled udp only objects")
elif ports.get("rant"):
rant2 = ports.get("rant")
tcpport = True
ran_tcp2 = (list(it.zip_longest(*[iter(rant2[0])] * 2)))
for rt in compile_rant_port2(ran_tcp2):
obj.append(rt)
print("compiled tcp only range objects")
elif ports.get("ranu"):
ranu2 = ports.get("ranu")
udpport = True
ran_udp2 = (list(it.zip_longest(*[iter(ranu2[0])] * 2))) # split strings by groups of 2 for port ranges
for ru in compile_rant_port2(ran_udp2):
obj.append(ru)
print("compiled udp only range objects")
elif ports.get("cm"):
tcpport = True
cm2 = ports.get("cm")
for c in compile_port2(cm2):
obj.append(c)
print("compiled worded objects\n\n")
else:
print("no items found")

The use of elif is to evaluate an else-if condition. So if the if condition is matched, it will not match any other elifs'.
If you want to process all the keys, you should multiple if conditions and not elif.
See below, a modified version
ports = {'tcp': [['10', '20']], 'rant': [['100', '200']], 'cm': ['https']}
if __name__ == "__main__":
obj = []
tcpport = []
udpport = []
mxport = []
items_found = False
if "tcp" in ports:
items_found=True
tcp2 = ports.get("tcp")
tcpport = True
for t in compile_port2(tcp2):
obj.append(t)
print("compiled tcp only objects")
if "udp" in ports:
items_found = True
udpport = True
udp2 = ports.get("udp")
for u in compile_port2(udp2):
obj.append(u)
print("compiled udp only objects")
if "rant" in ports:
items_found = True
rant2 = ports.get("rant")
tcpport = True
ran_tcp2 = (list(it.zip_longest(*[iter(rant2[0])] * 2)))
for rt in compile_rant_port2(ran_tcp2):
obj.append(rt)
print("compiled tcp only range objects")
if "ranu" in ports:
items_found = True
ranu2 = ports.get("ranu")
udpport = True
ran_udp2 = (list(it.zip_longest(*[iter(ranu2[0])] * 2))) # split strings by groups of 2 for port ranges
for ru in compile_rant_port2(ran_udp2):
obj.append(ru)
print("compiled udp only range objects")
if "cm" in ports:
items_found = True
tcpport = True
cm2 = ports.get("cm")
for c in compile_port2(cm2):
obj.append(c)
print("compiled worded objects\n\n")
if not items_found:
print("no items found")

Am I right in understanding that you are asking why the first clause
if ports.get("tcp"):
tcp2 = ports.get("tcp")
tcpport = True
for t in compile_port2(tcp2):
obj.append(t)
print("compiled tcp only objects")
Is the only one which runs when "tcp" is present in ports? That's how if elif else blocks are supposed to work. Elif stands for else if, i.e, "If the thing that came before we WASNT TRUE, then try this next"
If you want to to multiple things, then use many if blocks rather than elif.

Related

maya python api multmatrix plugin

I am studying with maya python api.
I'm making a simple mult_matrix node plugin, and for some reason, the multiplied output keeps coming out to zero. I'm going to receive the output by matrix.
Can you help me?
def compute(self,plug,data):
enter code here
if plug == node.Moutput:
readerMtx = data.inputValue(node.reader).asFloathMatrix()
targetMtx = data.inputValue(node.target).asFloathMatrix()
result = readerMtx * targetMtx
outputHandle = data.outputValue(node.Moutput)
outputHandle.setMFloatMatrix(result)
data.setClean(plug)
def initializer():
mtxAttr1 = OpenMaya.MFnMatrixAttribute()
node.reader = mtxAttr1.create("In_Matrix","reader",OpenMaya.MFnMatrixData.kMatrix)
mtxAttr1.setKeyable = True
mtxAttr1.setStorable = True
mtxAttr1.Readable = True
mtxAttr1.setWrit = True
mtxAttr2 = OpenMaya.MFnMatrixAttribute()
node.Target = mtxAttr2.create("Target_Matrix","reader",OpenMaya.MFnMatrixData.kMatrix)
mtxAttr2.setKeyable = True
mtxAttr2.setStorable = True
mtxAttr2.Readable = True
mtxAttr2.setWrit = True
mtxAttr3 = OpenMaya.MFnMatrixAttribute()
node.MOutput = mtxAttr3.create("In_Matrix","Moutput",OpenMaya.MFnMatrixData.kMatrix)
mtxAttr3.writable = True
mtxAttr3.keyable = True
node.addAttribute(node.reader)
node.addAttribute(node.Target)
node.addAttribute(node.MOutput)
node.AttributeAffects(node.reader , node.MOutput)
node.AttributeAffects(node.Target , node.MOutput)
Help me a lot!

how to use python serial write to PLC?

I have 2 PLCs with serial port. one is mitsubishi Q00Jcpu mc protocol, another is omron hostlink protocol.
I tried to use python pyserial lib to write to the PLC and read response.
But failed, I tried to use a serial tool to test and got nice response,
serial tool success communicate with PLC, I read CIO address start 100 and size 2, it got 12345678, that is a true result.
my code :
import serial
omr = serial.Serial(port='COM4', baudrate=9600, timeout=0.5)
omr.parity=serial.PARITY_EVEN
omr.bytesize = 7
omr.stopbits =2
resp = omr.write(b'\x40\x30\x30\x46\x41\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x31\x30\x31\x42\x30\x30\x30\x36\x34\x30\x30\x30\x30\x30\x32\x30\x35\x2a\x0d')
print(resp) # print 34
resp = omr.write(b'#00FA0000000000101B0006400000205*\CR')
print(resp) # print 36
It seems return the len of write data, I tried both hex and ascii, all failed.
I figured it how, the return of serial.write is not the result. If need the response from device, should use read_until(), not sure weather this is a good way, please let me know if you have any suggestions.
Anyway, the class i make, can read the omron PLC by giving different params, hope it can help someone.
DEMO:
import serial
# cmd = '0101B00064000001'
class OMR_SERIAL_TOOL:
def __init__(self,port,baudrate):
self.omr = serial.Serial(port=port, baudrate=baudrate, timeout=0.5)
self.omr.parity=serial.PARITY_EVEN
self.omr.bytesize = 7
self.omr.stopbits =2
self.head ='#00FA000000000'
#staticmethod
def get_xor(frame):
res = ord(frame[0])
for i in frame[1:]:
res ^= ord(i)
res = str(res)
if len(res) == 1:
res = '0'+res
return res
def omr_read(self,head,cmd):
xor = OMR_SERIAL_TOOL.get_xor(head+cmd)
self.omr.write('{}{}{}*\r'.format(head,cmd,xor).encode())
resp = self.omr.read_until("\r".encode())
return str(resp[23:-4],encoding='utf-8')
test = OMR_SERIAL_TOOL('COM4',9600)
res = test.omr_read(test.head,cmd='0101B00064000002')
print(res) # 12345678 , which is the correct response
BOOM! VERSION 1.0
import serial
class OMR_SERIAL_TOOL:
def __init__(self,port,baudrate,mode):
self.omr = serial.Serial(port=port, baudrate=baudrate, timeout=0.5)
self.omr.parity=serial.PARITY_EVEN
self.omr.bytesize = 7
self.omr.stopbits =2
# fins mdoe
if mode == 'fins':
self.head ='#00FA000000000'
self.cmd_map = {
"MEMORY_AREA_READ":"0101",
"MEMORY_AREA_WRITE":"0102",
"MEMORY_AREA_FILL":"0103",
"MULTI_MEMORY_AREA_READ":"0104",
"MEMORY_AREA_TRANSFER":"0105"
}
# cs/cj mode
self.io_memory_area_code_map={
"CIO_bit":"30",
"WR_bit":"31",
"HR_bit":"32",
"AR_bit":"33",
"CIO_word":"B0",
"WR_word":"B1",
"HR_word":"B2",
"AR_word":"B3"
}
#staticmethod
def get_xor(frame):
res = ord(frame[0])
for i in frame[1:]:
res ^= ord(i)
res = str(res)
if len(res) == 1:
res = '0'+res
res = str(hex(int(res)))[2:]
upcase_res = ''
for i in res:
if i.isdigit():
upcase_res += i
elif i.isalpha():
upcase_res += i.upper()
if len(upcase_res) == 1:
upcase_res = '0'+upcase_res
return upcase_res
def omr_read(self,cmd,code,address,size):
address = str(hex(address))[2:]
size = str(hex(size))[2:]
while len(address) < 4:
address = '0' + address
while len(size) < 4:
size = '0' + size
frame = self.head+cmd+code+address+'00'+size
xor = OMR_SERIAL_TOOL.get_xor(frame)
#print(frame+xor)
self.omr.write('{}{}*\r'.format(frame,xor).encode())
resp = self.omr.read_until("\r".encode())
return str(resp[23:-4],encoding='utf-8')
omr_client = OMR_SERIAL_TOOL('COM4',9600,'fins')
cmd = omr_client.cmd_map['MEMORY_AREA_READ']
code = omr_client.io_memory_area_code_map['CIO_word']
res = omr_client.omr_read(cmd,code,address=500,size=1)
I tested it good on CIO read, please let me know if you find any bugs.

Conditional list element value

I would like to make a dictionary to compare two values and see if they are equal or not. How would you do this (see value of compareDict -third element of list) since I get a syntax error.
Is there a more elegant way to do this?
def script_sanityCheck(shotDict):
#retrieve data from current script
script_frange = (nuke.root()['first_frame'].value(), nuke.root()['last_frame'].value())
script_fps = nuke.root()['fps'].value()
script_projectname = nuke.root()['project'].value()
script_code = nuke.root()['shotcode'].value()
script_neutralgrade = nuke.root()['neutralgrade_cdl'].value()
#extract data from dictionary
sg_frange = (shotDict['sg_cut_in'], shotDict['sg_cut_out'])
sg_fps = shotDict['sg_fps']
sg_projectname = shotDict['project.Project.name']
sg_code = shotDict['code']
sg_neutralgrade = shotDict['sg_neutralgrade_cdl']
#compare both
compareDict = {
'frange' : [script_frange, sg_frange, True if script_frange == sg_frange else False]
'fps' : [script_fps, sg_fps, True if script_fps == sg_fps else False]
'projectname' : [script_projectname, sg_projectname, True if script_projectname == sg_projectname else False ]
'code' : [script_code, sg_code, True if script_code == sg_code else False]
'neutralgrade' : [script_neutralgrade, sg_neutralgrade, True if script_neutralgrade == sg_neutralgrade else False]
}
pprint(script_sanityCheck(shotDict))
Use dicts from the start to organize your data. That will allow you to build your comparison with a dict comprehension:
def script_sanityCheck(shotDict):
#retrieve data from current script
script = {'frange': (nuke.root()['first_frame'].value(), nuke.root()['last_frame'].value()),
'fps': nuke.root()['fps'].value(),
'projectname': = nuke.root()['project'].value(),
'code': nuke.root()['shotcode'].value(),
'neutralgrade': nuke.root()['neutralgrade_cdl'].value()}
#extract data from dictionary
sg = {'frange': (shotDict['sg_cut_in'], shotDict['sg_cut_out']),
'fps': shotDict['sg_fps'],
'projectname': shotDict['project.Project.name'],
'code': shotDict['code'],
'neutralgrade': shotDict['sg_neutralgrade_cdl']}
#compare both
compareDict = {key: [script[key], sg[key], script[key] == sg[key]] for key in sg}
return compareDict
pprint(script_sanityCheck(shotDict))
Note also that True if a == b else False is simply a == b.

may ipaddress.collapse_addresses() collapse for more than 1 bit of the mask?

Why does:
>>> import ipaddress
>>> print [ip for ip in ipaddress.collapse_addresses([ipaddress.IPv4Network(u'192.0.128.0/24'), ipaddress.IPv4Network(u'192.0.129.0/24')])]
[IPv4Network(u'192.0.128.0/23')]
but:
>>> print [ip for ip in ipaddress.collapse_addresses([ipaddress.IPv4Network(u'192.0.129.0/24'), ipaddress.IPv4Network(u'192.0.130.0/24')])]
[IPv4Network(u'192.0.129.0/24'), IPv4Network(u'192.0.130.0/24')]
What I am trying to achieve:
>>> print [ip for ip in ipaddress.collapse_addresses([ipaddress.IPv4Network(u'192.0.129.0/24'), ipaddress.IPv4Network(u'192.0.130.0/24')])]
[IPv4Network(u'192.0.128.0/22')]
It seems like collapse_addresses cannot collapse for more than 1 bit of the mask.
import ipaddr
ips = [ipaddr.IPv4Address(ip) for ip in ['10.10.10.0','10.10.11.0']]
ips = sorted(ips)
lowest_ip = ips[0] #first
highest_ip = ips[-1] #last
mask_length = ipaddr._get_prefix_length(int(lowest_ip), int(highest_ip),
lowest_ip.max_prefixlen)
network_ip = ipaddr.IPNetwork("{}/{}".format(lowest_ip, mask_length)).network
network = ipaddr.IPNetwork("{}/{}".format(network_ip, mask_length), strict = True)
print (network)
$> 10.10.10.0/23
This function returns the smallest network that contain the ipv4 networks of a list:
ADDRESS_ANY = ip_address(u'0.0.0.0')
def one_net(subnets):
"""
Get the one IP network that covers all subnets in input,
or None is subnets are disjoint.
"""
if len(subnets) == 0:
return None
minlen = min([net.prefixlen for net in subnets])
while subnets.count(subnets[0]) < len(subnets) and minlen > 0:
# all subnets are not (yet) equal
subnets = [net.supernet(new_prefix=minlen) for net in subnets]
minlen -= 1
# 0.0.0.0/? -> no common subnet
if subnets[0].network_address == ADDRESS_ANY:
return None
return subnets[0]

Write using Configparser or propparser changes case of properties

i am using configparser or propparser to read a property from a file and adding it if it is not present
But adding the property using configparser or propparser, is changing the case of remaining properties
Following is my script
from ConfigParser import RawConfigParser
def modifyInstallProperties ():
propParser = RawConfigParser()
propParser.read('/home/ram/test.properties')
try:
ip = propParser.get('Client', 'export_sftp_identity_file')
print "ip is " +ip
except :
propParser.set('Client','#export_sftp_identity_file','/home/ram/.ssh/id_rsa')
with open('/home/ram/test.properties', 'w') as configfile:
propParser.write(configfile)
modifyInstallProperties()
i am writing property "export_sftp_identity_file", if it is no there, but it changes the case of remaining properties
before after
base_server_IP = 172.31.1.52 base_server_ip = 172.31.1.52 (ip instead of IP)
installShard = false installshard = false ( s instead of S in shard)
installDbServer = false installdbserver = false (d instead of D in Dbserver)
....
test.properties, before running the script
[Client]
enable_https_from_patch = false
client_install_dir = /centina/client
export_sftp_target_port = 22
client_jboss_dir = /centina/client/jboss-eap-5.2.0
base_server_IP = 172.31.1.52
export_sftp_target_host = 172.31.1.52
enable_https = false
export_sftp_target_password = centina
enable_http = true
export_sftp_target_user = centina
[Common]
db_pm_port = 3306
installShard = false
db_sla_port = 3306
jdk_dir = /opt/jdk
installDbServer = false
installDbMultiple = false
installOnlyDbServer = false
installClientServer = false
installLoader = false
installMedMultiple = false
db_sa_port = 3306
db_server_IP = 172.31.1.52
installDbSlave = false
installOnlyMedServer = false
server_bind_ip = 0.0.0.0
installMedServer = false
db_fm_port = 3306
standAloneInstallation = false
installAppServer = false
db_spm_port = 3306
after running the script
[Client]
enable_https_from_patch = false
client_install_dir = /centina/client
export_sftp_target_port = 22
client_jboss_dir = /centina/client/jboss-eap-5.2.0
base_server_ip = 172.31.1.52
export_sftp_target_host = 172.31.1.52
enable_https = false
export_sftp_target_password = centina
enable_http = true
export_sftp_target_user = centina
#export_sftp_identity_file = /home/centina/.ssh/id_rsa
[Common]
db_pm_port = 3306
installshard = false
db_sla_port = 3306
jdk_dir = /opt/jdk
installdbserver = false
installdbmultiple = false
installonlydbserver = false
installclientserver = false
installloader = false
installmedmultiple = false
db_sa_port = 3306
db_server_ip = 172.31.1.52
installdbslave = false
installonlymedserver = false
server_bind_ip = 0.0.0.0
installmedserver = false
db_fm_port = 3306
standaloneinstallation = false
installappserver = false
db_spm_port = 3306
How to solve this

Categories