How can I run through all these ifs in python? - json

When I run the program It will only run the first If and make those specific changes. Noticed when i switched them around and only the first one gives me what I want... Thanks for the help.
if SW1 != r['SW1']: #check the received value of SW1 & change it on the App if there is a mismatch
print("Changing SW1 status to the value in the database.")
if self.sw1.active == True:
self.sw1.active = False
else:
self.sw1.active = True
else:
return
if LED1 != r['LED1']: #check the received value of led1 & change it on the App if there is a mismatch
print("Changing LED1 status to the value in the database.")
if self.led1.active == True:
self.led1.active = False
else:
self.led1.active = True
else:
return
if LED2 != r['LED2']: #check the received value of led2 & change it on the App if there is a mismatch
print("Changing LED2 status to the value in the database.")
if self.led2.active == True:
self.led2.active = False
else:
self.led2.active = True
else:
if LED3 != r['LED3']: #check the received value of led3 & change it on the App if there is a mismatch
print("Changing LED3 status to the value in the database.")
if self.led3.active == True:
self.led3.active = False
else:
self.led3.active = True
else:
return

You should not return in else after every if. This will make the function to close after the first if is failed. I will explain it further with one example.
Take this function which checks if a number is even.
def foo_bar(n):
if n%2==0:
print("Even")
else:
return
print("I have been reached")
If an even number is passed, you will see the below output
>>> foo_bar(10)
Even
I have been reached
If the Odd number is passed, you will not see any output as the function is returning None and Terminated in else.
Now if you have multiple ifs in the function,
def foo_bar(n):
if n%2==0:
print("Even")
else:
return
if n%3==0:
print("Divisible by 3")
print("I have been reached")
If you pass 9 as an argument, the above function prints nothing. It is because after one condition is checked , you are returning None which terminates the function.
Hope this answers your question.

Related

Why am I not being able of detecting a None value from a dictionary

I have seen this issue many times happening to many people (here). I am still struggling trying to validate whether what my dictionary captures from a JSON is "None" or not but I still get the following error.
This code is supposed to call a CURL looking for the 'closed' value in the 'status' key until it finds it (or 10 times). When payment is done by means of a QR code, status changes from opened to closed.
status = (my_dict['elements'][0]['status'])
TypeError: 'NoneType' object is not subscriptable
Any clue of what am I doing wrong and how can I fix it?
Also, if I run the part of the script that calls the JSON standalone, it executes smoothly everytime. Is it anything in the code that could be affecting the CURL execution?
By the way, I have started programming 1 week ago so please excuse me if I mix concepts or say something that lacks of common sense.
I have tried to validate the IF with "is not" instead of "!=" and also with "None" instead of "".
def show_qr():
reference_json = reference.replace(' ','%20') #replaces "space" with %20 for CURL assembly
url = "https://api.mercadopago.com/merchant_orders?external_reference=" + reference_json #CURL URL concatenate
headers = CaseInsensitiveDict()
headers["Authorization"] = "Bearer MY_TOKEN"
pygame.init()
ventana = pygame.display.set_mode(window_resolution,pygame.FULLSCREEN) #screen settings
producto = pygame.image.load("qrcode001.png") #Qr image load
producto = pygame.transform.scale(producto, [640,480]) #Qr size
trials = 0 #sets while loop variable start value
status = "undefined" #defines "status" variable
while status != "closed" and trials<10: #to repeat the loop until "status" value = "closed"
ventana.blit(producto, (448,192)) #QR code position setting
pygame.display.update() #
response = requests.request("GET", url, headers=headers) #makes CURL GET
lag = 0.5 #creates an incremental 0.5 seconds everytime return value is None
sleep(lag) #
json_data = (response.text) #Captures JSON response as text
my_dict = json.loads(json_data) #creates a dictionary with JSON data
if json_data != "": #Checks if json_data is None
status = (my_dict['elements'][0]['status']) #If json_data is not none, asigns 'status' key to "status" variable
else:
lag = lag + 0.5 #increments lag
trials = trials + 1 #increments loop variable
sleep (5) #time to avoid being banned from server.
print (trials)
From your original encountered error, it's not clear what the issue is. The problem is that basically any part of that statement can result in a TypeError being raised as the evaluated part is a None. For example, given my_dict['elements'][0]['status'] this can fail if my_dict is None, or also if my_dict['elements'] is None.
I would try inserting breakpoints to better assist with debugging the cause. another solution that might help would be to wrap each part of the statement in a try-catch block as below:
my_dict = None
try:
elements = my_dict['elements']
except TypeError as e:
print('It possible that my_dict maybe None.')
print('Error:', e)
else:
try:
ele = elements[0]
except TypeError as e:
print('It possible that elements maybe None.')
print('Error:', e)
else:
try:
status = ele['status']
except TypeError as e:
print('It possible that first element maybe None.')
print('Error:', e)
else:
print('Got the status successfully:', status)

Lua - Concatinate several arguments passed into a function, until condition is met, then pass string to next function

pvMessage is sent from another function, the message often comes in a few parts almost instantly. I am looking to store the pvMessages and concatinate the message to the last. Therefore a master string is created with all parts.
Example.
pvMessage #1 = thisispart1msg
pvMessage #2 = now part two is being received
pvMessage #3 = Part 3
MasterMessage = thisispart1msgnow part two is being receivedPart 3
I have tried several attempts at solving this issue. The storing of the message outside the function is proving harder then I though, I keep overwriting the previous message.
function ProcessClientMessage( pvMessage )
if StartMessage == "" then
StartMessage = pvMessage
pvMessage = ""
end
if pvMessage ~= "" then
if MiddleMessage == "" then
MiddleMessage = pvMessage
pvMessage = StartMessage .. MiddleMessage
pvMessage = ""
end
end
if pvMessage ~= "" then
if EndMessage == "" then
EndMessage = pvMessage
pvMessage = StartMessage .. MiddleMessage .. EndMessage
pvMessage = ""
end
end
if pvMessage ~= "" then
ProcessClientMessageReset()
end
end
If there are always three parts that you want to concatenate, something like this may work:
local buffer = {}
local function ProcessClientMessage(pvMessage)
if #buffer < 3 then
table.insert(buffer, pvMessage)
else
--ProcessClientMessageReset(table.concat(buffer, ""))
print(table.concat(buffer, ""))
buffer = {}
end
end
ProcessClientMessage("thisispart1msg")
ProcessClientMessage("now part two is being received")
ProcessClientMessage("Part 3")
ProcessClientMessage("more thisispart1msg")
ProcessClientMessage("some now part two is being received")
ProcessClientMessage("Part 4")
This should print:
thisispart1msgnow part two is being receivedPart 3
more thisispart1msgsome now part two is being receivedPart 4
This problem also be solved with coroutines:
local function consumer(consume)
print(consume()..consume()..consume())
return consumer(consume)
end
local process = coroutine.wrap(consumer)
process(coroutine.yield)
process('foo')
process('bar')
process('baz')
process('hello')
process('world')
process('test')
EDIT: As Egor pointed out, the order of evaluation isn't technically defined (although it's left to right in every Lua implementation I'm aware of) so here's an alternative that would work even if your interpreter was doing gcc -O3-like optimizations:
local function consumer(consume)
local a = consume()
local b = consume()
local c = consume()
print(a .. b .. c)
return consumer(consume)
end
You can make use of the "or" assignment to simplify initialization of the global variable and then concatenate the string to the result. Consider:
function ProcessClientMessage(msg)
msg_global_ = (msg_global_ or "")..msg
print(msg_global_) -- Just for debug purposes so we can print each step
end
do
ProcessClientMessage("thisispart1msg")
ProcessClientMessage("now part two is being received")
ProcessClientMessage("Part 3")
end
The variable msg_global_ contains the string being built. If it has not been added too yet, then it will be nil. In this case the or "" will be executed and default the string empty.
We then simply append the string msg.
The output looks like:
thisispart1msg
thisispart1msgnow part two is being received
thisispart1msgnow part two is being receivedPart 3
When you actually process the message, just set the global variable to nil and you are good to go again.

If statement not returning the desired result

I'm new to Python and I believe the issue with my code is being caused by the fact that I'm a newbie and there's some theory or something that I must not be familiar with yet.
Yes, this question was asked before but, is different from mine. Believe me I tried everything that I thought that needs to be done.
Everything worked until I added everything in "if five in silos" statement.
After I enter the values for the 6 input functions, the program just finishes with exit code 0. Nothing else happens. The for loop is not initiated.
I want for the code to accept either 103 or 106 when prompting to enter something for the "five" variable.
I'm using PyCharm and Python 3.7.
import mysql.connector
try:
db = mysql.connector.connect(
host="",
user="",
passwd="",
database=""
)
one = int(input("Number of requested telephone numbers: "))
two = input("Enter the prefix (4 characters) with a leading 0: ")[:4]
three = int(input("Enter the ccid: "))
four = int(input("Enter the cid: "))
six = input("Enter case number: ")
five = int(input("Enter silo (103, 106 only): "))
cursor = db.cursor()
cursor.execute(f"SELECT * FROM n1 WHERE ddi LIKE '{two}%' AND silo = 1 AND ccid = 0 LIMIT {one}")
cursor.fetchall()
silos = (103, 106)
if five in silos:
if cursor.rowcount > 0:
for row in cursor:
seven = input(f"{row[1]} has been found on our system. Do you want to continue? Type either Y or N.")
if seven == "Y":
cursor.execute(f"INSERT INTO n{five} (ddi, silo, ccid, campaign, assigned, allocated, "
f"internal_notes, client_notes, agentid, carrier, alias) VALUES "
f"('{row[1]}', 1, {three}, {four}, NOW(), NOW(), 'This is a test.', '', 0, "
f"'{row[13]}', '') "
f"ON DUPLICATE KEY UPDATE "
f"silo = VALUES (silo), "
f"ccid = VALUES (ccid), "
f"campaign = VALUES (campaign);")
cursor.execute(f"UPDATE n1 SET silo = {five}, internal_notes = '{six}', allocated = NOW() WHERE "
f"ddi = '{row[1]}'")
else:
print("The operation has been canceled.")
db.commit()
else:
print(f"No results for prefix {two}.")
else:
print("Enter either silo 103 or 106.")
cursor.close()
db.close()
except (ValueError, NameError):
print("Please, enter an integer for all questions, except case number.")
Because it must be:
for row in cursor.fetchall():
// do something
In your code cursor returns a Python Class defined by db.cursor() but you need to call the fetchall() function to read the rows contained in it.
You're actually calling cursor.fetchall() without doing nothing with it, you can assign the call to a variable and than do this:
result = cursor.fetchall()
for row in result:
//do something
I found the problem: I had to store cursor.fetchall() into a variable.
After I put: eight = cursor.fetchall() before the "silos" tuple, everything worked perfectly.

Creating a Caesar Cipher Program in Python 3.4, but function doesn't work

Currently, I am creating a Caesar Cipher but it is not working correctly, can anyone help at all? The code will be below. At the moment, if the program is run first time (as in, no functions have to be re run) it works perfectly, but when the getKey() function is re run, it returns an error. After the code, the error is shown:
def runProgram():
def choice():
userChoice = input("Do you wish to Encrypt of Decrypt? Enter E or D: ").lower()
if userChoice == "e":
return userChoice
elif userChoice == "d":
return userChoice
else:
print("Invalid Response. Please try again.")
choice()
def getMessage():
userMessage = input("Enter your message: ")
return userMessage
def getKey():
try:
userKey = int(input("Enter a key number (1-26): "))
except:
print("Invalid Option. Please try again.")
getKey()
else:
if userKey < 1 or userKey > 26:
print("Invalid Option. Please try again.")
getKey()
else:
return userKey
def getTranslated(userChoice, message, key):
translated = ""
if userChoice == "e":
for character in message:
num = ord(character)
num += key
translated += chr(num)
savedFile = open('Encrypted.txt', 'w')
savedFile.write(translated)
savedFile.close()
return translated
else:
for character in message:
num = ord(character)
num -= key
translated += chr(num)
return translated
userChoice = choice() #Runs function for encrypt/decrypt selection. Saves choice made.
message = getMessage() #Run function for user to enter message. Saves message.
key = getKey() #Runs function for user to select key. Saves key choice.
translatedMessage = getTranslated(userChoice, message, key) #Runs function to translate message, using the choice, message and key variables)
print("\nTranslation complete: " + translatedMessage)
runProgram()
I have tried to create it error proof during the getKey() function with the try, except and else commands. It will 'Try' to see that the input is an int or not, if it is, it goes to else, but if it isn't an int, then it will rerun the function. If the function is rerun, and an int is entered, this error is given:
This is an example of it working:
Do you wish to Encrypt of Decrypt? Enter E or D: E
Enter your message: Hello
Enter a key number (1-26): 5
Translation complete: Mjqqt
This is an example when the getKey() function must be re run due to an int not being entered:
Do you wish to Encrypt of Decrypt? Enter E or D: E
Enter your message: Hello
Enter a key number (1-26): H
Invalid Option. Please try again.
Enter a key number (1-26): 5
Traceback (most recent call last):
File "C:\Python34\Encryptor2.py", line 54, in
runProgram()
File "C:\Python34\Encryptor2.py", line 52, in runProgram
translatedMessage = getTranslated(userChoice, message, key) #Runs function to translate message, using the choice, message and key variables)
File "C:\Python34\Encryptor2.py", line 35, in getTranslated
num += key
TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType'
As you can see, it re runs the function as I want it too, but the error occurs when adding the key to the ord of character.
The first call to getKey(), with your comment:
key = getKey() #Runs function for user to select key. Saves key choice.
Another place you call it:
if userKey < 1 or userKey > 26:
print("Invalid Option. Please try again.")
getKey()
If you were to write that with the same kind of comment, it would be:
getKey() #Runs function for user to select key. Doesn't save key choice.
What the user types in, comes out of getKey() ... and you aren't keeping track of it, so it vanishes. You then do.
return userKey
userKey is still the H you tried to convert to int, the one that failed. You didn't get rid of it, so it's still there.
The better solution is to rework the shape of your code, so getKey() never calls getKey() inside itself. Do the error checking outside, perhaps, like this kind of shape:
def getKey():
prompt user for key
try to convert to int and return the int
if it fails, return None as an indication that getting the key went wrong.
key = None #set some wrong placeholder
while (key is None) or (key < 1) or (key > 26):
key = getKey()
change your input to raw_input
just use the maketrans and translate functions that basically encrypt or decrypt the message for you.they make for a very short and efficient solution to the problem
message = input('enter message').lower()
offset = int(input('enter offset (enter a negative number to decrypt)'))
alphabet = 'abcdefghijklmnopqrstuvwxyz'
enc_alphabet = (alphabet[alphabet.index(alphabet[offset]):len(alphabet)])+ alphabet[0:offset]
data = str.maketrans(alphabet,enc_alphabet)
final_message = str.translate(message, data)
print(final_message)
This code really doesn't need to be this complicated at all, if you just use regex the code will be much shorter but (in my opinion) way better.
Here's a code I created for Caesar cipher encrypting, decrypting and using a shift of the user's choice using regex.
import re
def caesar(plain_text, shift):
cipherText = ''
for ch in plain_text:
stayInAlphabet = ord(ch) + shift
if ch.islower():
if stayInAlphabet > ord('z'):
stayInAlphabet -= 26
elif stayInAlphabet < ord('a'):
stayInAlphabet += 26
elif ch.isupper():
if stayInAlphabet > ord('Z'):
stayInAlphabet -= 26
elif stayInAlphabet < ord('A'):
stayInAlphabet += 26
finalLetter = chr(stayInAlphabet)
cipherText += finalLetter
print(cipherText)
return cipherText
selection = input ("encrypt/decrypt ")
if selection == 'encrypt':
plainText = input("What is your plaintext? ")
shift = (int(input("What is your shift? ")))%26
caesar(plainText, shift)
else:
plainText = input("What is your plaintext? ")
shift = ((int(input("What is your shift? ")))%26)*-1
caesar(plainText, shift)

Lua: How to execute different blocks depending on conditions?

I have this table:
no_table ={
{a="3", b="22", c="18", d="ABC"},
{a="4", b="12", c="25", d="ABC"},
{a="5", b="15", c="16", d="CDE"},
}
This function:
function testfoo()
i = 1
while no_table[i] ~= nil do
foo(no_table[i])
i = i + 1
end
end
and the foo function:
function foo(a,b,c,d)
if no_table[i][4] ~= no_table[i-1][4]
then
print (a+b)
elseif no_table[i][4] == no_table[i-1][4]
then
print (b+c)
end
end
Can you help me find? :
A way to be able to check if the two tables are or not equal (currently it gives me cannot index nil)
A way to execute only the "print (b+c)" code if the equality is true, or if is not true then both "print (a+b)" first and "print (b+c) secondly without duplicating the code.
Lots of problems I'm seeing in this. First, I'd never rely on i being set in an external function, it really should be a local variable and passed as a parameter if you need it. That said, you need to check if no_table[x] exists before trying to access no_table[x][y]. So, for foo you'd have:
function foo(a,b,c,d)
if not (no_table[i] and no_table[i-1] and no_table[i][4] == no_table[i-1][4])
then
print (a+b)
elseif no_table[i] and no_table[i-1] and no_table[i][4] == no_table[i-1][4]
then
print (b+c)
end
end
Also, for numbers in the table, if you want to do arithmetic, you need to remove the quotes:
no_table ={
{a=3, b=22, c=18, d="ABC"},
{a=4, b=12, c=25, d="ABC"},
{a=5, b=15, c=16, d="CDE"},
}
Next, in testfoo, you're passing a table, so you either need to split out the values of a, b, c, and d on your function call, or you can just pass the table itself and handle that in foo:
function foo(t)
if not (no_table[i] and no_table[i-1] and no_table[i][4] == no_table[i-1][4])
then
print (t.a+t.b)
elseif no_table[i] and no_table[i-1] and no_table[i][4] == no_table[i-1][4]
then
print (t.b+t.c)
end
end
This results in:
> testfoo()
25
37
31
Edit: One final cleanup, since the conditions are the same, you can use an else rather than an elseif:
function foo(t)
if no_table[i] and no_table[i-1] and no_table[i][4] == no_table[i-1][4]
then
print (t.b+t.c)
else
print (t.a+t.b)
end
end