Using If statement to call a functions in Python - python

I am running a code to create cloudformation stack, delete stack, update stack with defined parameter variable using json file using python.
I have defined a 3 different statement under init() function. I need to put a if condition:
if i want to create a stack, it will call "create_products"
else, update a stack, it will call "update_products"
elif, delete a stack, it will update "delete_products"
from __future__ import print_function
import subprocess
import json
import yaml
import sys
import os
import re
import boto3
from glob import glob
def createstack(productName, productId, paramlist):
try:
client = boto3.client('servicecatalog', region_name='us-east-1')
ProvisioningArtifactId = client.list_provisioning_artifacts(ProductId=productId)
ArtifactId = ProvisioningArtifactId['ProvisioningArtifactDetails'][0]['Id']
response = client.provision_product(ProvisionedProductName=productName, ProductId=productId, ProvisioningArtifactId=ArtifactId, ProvisioningParameters=paramlist)
print(response)
except Exception as e:
error = "An error occurred processing this request: " + str(e)
print(error)
def updatestack(productName, productId, paramlist):
try:
client = boto3.client('servicecatalog', region_name='us-east-1')
ProvisioningArtifactId = client.list_provisioning_artifacts(ProductId=productId)
ArtifactId = ProvisioningArtifactId['ProvisioningArtifactDetails'][0]['Id']
response = client.update_provisioned_product(ProvisionedProductName=productName, ProductId=productId, ProvisioningArtifactId=ArtifactId, ProvisioningParameters=paramlist)
print(response)
except Exception as e:
error = "An error occurred processing this request: " + str(e)
print(error)
def deletestack(productName):
try:
client = boto3.client('servicecatalog', region_name='us-east-1')
response = client.terminate_provisioned_product(ProvisionedProductName=productName)
print(response)
return response
except Exception as e:
error = "An error occurred processing this request: " + str(e)
return(error)
def init():
#global args
with open("list_provisional_product.json") as f:
product_list = json.load(f)
with open("testing-pipeline-params.json") as f:
baselist = json.load(f)
for product in product_list["update_products"]:
for provisioned_product_name in product["provisioned_product_names"]:
updatestack(productName=provisioned_product_name, productId=product["product_id"], paramlist=baselist[provisioned_product_name])
for product in product_list["delete_products"]:
for provisioned_product_name in product["provisioned_product_names"]:
deletestack(productName=provisioned_product_name)
for product in product_list["create_products"]:
for provisioned_product_name in product["provisioned_product_names"]:
createstack(productName=provisioned_product_name, productId=product["product_id"], paramlist=baselist[provisioned_product_name])
def main():
init()
if __name__== "__main__":
main()

Yes, You have to get operation name(Create/ Update/ Delete) from user via command line argument or ask user during code execution via input function.
Demo 1: Get Operation name from command line argument by using sys.argv
You have to give operation name when you run your python code. Here Py file name is if_loop.py
import sys
print("arg:", sys.argv)
try:
operation_name = sys.argv[1].lower()
except IndexError:
print("Argument is missing")
exit()
if operation_name == "create":
print("Call Create function")
elif operation_name == "update":
print("Call Update function")
elif operation_name == "delete":
print("Call Dale function")
else:
print("Invalid Operation name")
Output
Invalid Operation name
(env) PS C:\Users\vivek\Documents\Workplace\stackoverflow> python .\if_loop.py Create
arg: ['.\\if_loop.py', 'Create']
Call Create function
Demo 2: Using input function
operation_name = input("Give Operation Name:").lower()
if operation_name == "create":
print("Call Create function")
elif operation_name == "update":
print("Call Update function")
elif operation_name == "delete":
print("Call Dale function")
else:
print("Invalid Operation name")
Output
Give Operation Name:Update
Call Update function

Thank you so much Vivek ! I would rather go with approach 1st ie argv and it actually worked based on my need !! BRAVO

Related

I cannot execute my class because my class has no attribute 'execute'`?

I have my class here:
I have my code here:
import logging
import pymysql as pm
import os
import json
class className:
env=None
config=None
def __init__(self, env):
self.config=className.get_config(env)
self.env=env
def get_config(env):
cwd=os.getcwd()
f=open(cwd+"\config_file_name"+".json")
f_config=json.load(f)
f.close()
return f_config
def DB_connection(env):
cnxn = pm.connect(
user="+username+",
password="+password+",
host="+host+",
port="+port+",
database="+database+"
)
def table1():
cnxn=None
cnxn=className.DB_connection
cur=cnxn.cursor()
table1_INSERT_QUERY="CALL sp_table1_Insert_Daily_Records();"
table1_EXCEPTIONS_QUERY="CALL sp_table1_Exceptions();"
try:
cur.execute(table1_INSERT_QUERY)
cnxn.commit()
except pm.Error as e:
print(f"Error: {e}")
except Exception as e:
logging.exception(e)
else:
print("table1 insertion query ran successfully, {} records updated.".format(cur.rowcount))
try:
cur.execute(table1_EXCEPTIONS_QUERY)
cnxn.commit()
except pm.Error as e:
print(f"Error: {e}")
except Exception as e:
logging.exception(e)
else:
print("table1 exceptions query ran successfully, {} exceptions updated.".format(cur.rowcount))
cnxn.close()
def main():
ve=className
ve.execute()
if __name__ == "__main__":
main()
I am trying to execute my class so it can execute my functions. Basically it creates an exceptions report defining what records are missing from yesterday. This function executes a stored procedure. I get the error saying:
AttributeError: type object 'className' has no attribute 'execute'
How do I execute my class and my functions?
The initial problem is that your class method is table1() but you are calling execute(). After that things get a little muddles between class and instance.
I would try what this does for you. Note this is untested.
import json
import logging
import pymysql
class ClassName:
def __init__(self, env_filename):
self.env = env_filename
self.config = self.get_config()
def get_config(self):
with open(self.env) as file_in:
return json.load(file_in)
def DB_connection(self):
return pymysql.connect(
user=self.config["+username+"],
password=self.config["+password+"],
host=self.config["+host+"],
port=self.config["+port+"],
database=self.config["+database+"]
)
def execute(self):
table1_INSERT_QUERY = "CALL sp_table1_Insert_Daily_Records();"
table1_EXCEPTIONS_QUERY = "CALL sp_table1_Exceptions();"
with self.DB_connection() as cnxn:
with cnxn.cursor() as cur:
try:
cur.execute(table1_INSERT_QUERY)
print("table1 insertion query ran successfully, {} records updated.".format(cur.rowcount))
cur.execute(table1_EXCEPTIONS_QUERY)
print("table1 exceptions query ran successfully, {} exceptions updated.".format(cur.rowcount))
except pymysql.Error as e:
print(f"Error: {e}")
except Exception as e:
logging.exception(e)
else:
cur.commit()
def main():
ve = ClassName("<path to env file>")
ve.execute()
if __name__ == "__main__":
main()

Using threading causes a mess in my terminal

I'm trying to create a program that automatically creates accounts upon available usernames using api calls. The program works fine. However, I want it to run faster. Therefore I tried using threading but the problem is that whenever I use more than one thread my terminal creates a big mess. youtube video on what happens.
My code:
# Login --> Threading --> Checker
def login(self):
self.headers["Authorization"] = "Basic " + self.finalLogin
r = requests.post("https://public-ubiservices.ubi.com/v3/profiles/sessions", json={"Content-Type":"application/json"}, headers=self.headers)
if r.status_code == 200:
if r.json()["ticket"]:
token = "Ubi_v1 t=" + r.json()["ticket"]
self.headers['Authorization'] = token
self.threading()
def checker(self):
[self.usernames.put(line.strip()) for line in open("external/wordlist.txt")]
while not self.usernames.empty():
name = self.usernames.get(); self.usernames.put(name)
url = f"https://public-ubiservices.ubi.com/v3/profiles?nameOnPlatform={name}&platformType=uplay"
try:
r = requests.get(url, headers=self.headers)
if self.checkedCount % 100 == 0:
self.checkedCount += 1
print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Message: Using new login")
self.accounts()
ctypes.windll.kernel32.SetConsoleTitleW(f"Gx | Checked: {self.checkedCount}, Available: {self.availableCount}, Errors: {self.errorCount}")
if r.status_code == 200:
self.checkedCount += 1
if len(r.json()['profiles']) != 0:
print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Taken: {name}")
else:
print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Available: {name}")
self.availableCount += 1
self.create(name)
else:
self.errorCount += 1
print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Error: Check errors.txt")
with open('external/errors.txt', "a") as errorFile:
errorFile.write(f'{self.currentTime} | Error code: {r.status_code}, Error message: {r.text}\n')
self.checkedCount += 1
self.accounts()
except Exception:
self.errorCount += 1
pass
def threading(self):
[self.usernames.put(line.strip()) for line in open("external/wordlist.txt")]
for x in range(5):
threading.Thread(target=self.checker, args=()).start()
What you call a mess it what happens, when using print while running multiple threads. This is, because print, especially the output buffer, is not thread safe. As described in more detail here, you must use a thread safe approach.
I think of two options:
Using a lock on the print statement, e.g.
from threading import Lock
print_lock = Lock()
with print_lock:
print(...)
Using a wrapper function (taken from here) and use that wrapper function to print things:
def safe_print(*args, sep=" ", end="", **kwargs):
joined_string = sep.join([ str(arg) for arg in args ])
print(joined_string + "\n", sep=sep, end=end, **kwargs)

How do you store the click command line arguments/options for reference?

New to click here so I'm still learning. How do I store the click arguments/options in an object for later reference within my application? I thought of just creating an object and returning it from the setup function, but it doesn't seem to work. Here is what I did:
import click
import sys
class Cfg(object):
component = ""
command = ""
obj = ""
my_cfg = Cfg()
#click.command()
#click.argument('component')
#click.argument("command")
#click.argument("obj")
def set_args(component, command, obj):
cfg = Cfg()
if component != "optdata":
sys.stderr.write("Invalid option")
sys.exit(1)
else:
cfg.component = component
cfg.command = command
cfg.obj = obj
return cfg
if __name__ == "__main__":
app_cfg = Cfg()
app_cfg = set_args() # Never actually completes here.
print("Component = ", app_cfg.component, "Command = ", app_cfg.command, "Obj = ", app_cfg.obj)
There is some sort of exception raised in core.py which just does a sys.exit and doesn't raise any sort of actual error.
Your design goes against the idea of Click: You're not supposed to treat "parsing the options" and "doing the work" as two separate steps:
import click
#click.command()
#click.argument("component", type=click.Choice(["optdata"]))
#click.argument("command")
#click.argument("obj")
def cli(component, command, obj):
print("Component = ", component, "Command = ", command, "Obj = ", obj)
# put your business logic here
if __name__ == "__main__":
cli()
The pattern is to call the function that processes the command line options and then have that function call any other functionality.

How to handle all errors from Python multiple pools?

to demonstrate problem I've prepared simple code:
from multiprocessing import Pool
class MyError(Exception):
def __str__(self):
return repr("Error msg: " + self.args[0])
def pool_function(msg):
print msg
raise MyError(msg)
return 0
def some_function():
my_pool = Pool(2)
msg = ['first', 'second']
my_pool.map(pool_function, msg)
if __name__ == '__main__':
try:
some_function()
except MyError, msg:
print msg
In this particular example as output I get:
first
second
'Error msg: first'
but I need rather:
first
second
'Error msg: first'
'Error msg: second'
Problem is that on the level of the main function I try to get access to all error messages which are unique, rather than handling it on level of pool_function but I get only first error msg. Unfortunately the real code with which I work is much more complex so is rather hard to do something with the structure of this code which is demonstrated in example. I need some clean and straight forward solution to get all error messages and process it on the level of main function.
Thanks in advice for any solutions.
You have to put try~ except in your pool_function not __main__. If no, __main__ will stop after the first except raised and left no chance for the second one to run. This is following what you are trying:
def pool_function(msg):
print msg
try:
raise MyError(msg)
except:
return MyError(msg)
def some_function():
my_pool = Pool(2)
msg = ['first', 'second']
return my_pool.map(pool_function, msg)
if __name__ == '__main__':
try:
msg= some_function()
except MyError, msg:
print msg
It works, but seem not a good way, so:
def pool_function(msg):
print msg
try:
# do something
raise MyError(msg)
except:
return 0,MyError(msg)
else:
return 1,# some result
def some_function():
my_pool = Pool(2)
msg = ['first', 'second']
return return my_pool.map(pool_function, msg)
if __name__ == '__main__':
msg = some_function()
for result in msg:
if result[0]:
# do something when it run successfully
elif not result[0]:
print result[1]
# do something when it got errors

Detect and print if no command line argument is provided

This is the program I have:
from sys import argv
script, arg1 = argv
def program(usr_input, arg1):
if(usr_input == arg1):
print "CLI argument and user input are identical"
else:
print "CLI argument and user input aren't identical"
if arg1 != "":
usr_input = raw_input("enter something: ")
program(usr_input, arg1)
else:
print "You have not entered a CLI argument at all."
I get:
Traceback (most recent call last):
File "filename.py", line 3, in <module>
script, arg1 = argv
ValueError: need more than 1 value to unpack
How can I detect the lack of command line argument and throw an error/exception instead of receiving this error?
I would recommend just checking the program args in the __main__ location of your script, as an entry point to the entire application.
import sys
import os
def program(*args):
# do whatever
pass
if __name__ == "__main__":
try:
arg1 = sys.argv[1]
except IndexError:
print "Usage: " + os.path.basename(__file__) + " <arg1>"
sys.exit(1)
# start the program
program(arg1)
You can handle the exception:
In [6]: def program(argv):
try:
script, argv1 = argv
except ValueError:
print("value error handled")
...:
In [7]: program(argv)
value error handled
try this:
script = argv[0]
try:
arg1 = argv[1]
except:
arg1 = ''
You could use a try statement there:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import sys
class MyError(Exception):
def __init__(self, value):
self.error_string = value
def __str__(self):
return eval(repr(self.error_string))
try:
script, arg1 = sys.argv
except ValueError:
raise MyError, "Not enough arguments"
Seeing that sys.argv is a list you should check the length of the list to make sure it is what you wish it to be. Your script with minor changes to check the length:
from sys import argv
def program(usr_input, arg1):
if(usr_input == arg1):
print "CLI argument and user input are identical"
else:
print "CLI argument and user input aren't identical"
if len(argv)== 2:
arg1 = argv[1]
usr_input = raw_input("enter something: ")
program(usr_input, arg1)
else:
print "You have not entered a CLI argument at all."

Categories