Try/Exception giving multiple results in Python - python

I have this program that should take the user input (an application name installed) and then it will open the application with subprocess.Popen() . All posibles application names are in a dictionary as keys, and the value is the path to the application .exe file. I'm using a try/Exception to see if there will be a KeyError (if the input name doens't exist in the dictionary).
So the programm should take the user input, see if the application name is in the dictionary, and then open the application. If the name isn't on the dictionary, it will give an error message and then ask for a name again.
But when I enter a non-existent name n times, it will run the finally block n times too. How to solve this?
import subprocess
apps ={
"vlc":"app_path\\vlc.exe",
"sublime":"app_path\\sublime_text.exe",
"chrome":"app_path\\chrome.exe",
"opera":"app_path\\launcher.exe",
"torrent":"app_path.\\qbittorrent.exe"
}
def test():
answer = str(input("What program do you want to run: ")).lower()
try:
print(apps[answer])
except KeyError:
print(f"{answer.capitalize()} application unknown. Try again with a valid application name")
print("===============================================================")
test()
except:
print("==============================")
print("Unknown error.")
else:
subprocess.Popen(apps[answer])
finally:
print("===========================================")
print("FINISHED")
test()

You're using recursion here, so obviously the finally block will run as many times as you enter call the function.
The code within finally is always executed regardless if the try block raises an error or not.
W3Schools has good examples for this: https://www.w3schools.com/python/python_try_except.asp
Instead of using try/except, you can simply use a while loop and apps.get(answer, 'ERROR') or if answer in apps to check if the entered input is in the apps dictionary. The following solution may be optimal.
def test():
while True:
answer = input("What program do you want to run: ").lower()
if answer in apps:
try:
res = subprocess.Popen(apps[answer]).communicate()
print("===========================================")
print("FINISHED")
return res
except:
print("==============================")
print("Unknown error.")
else:
print(f"{answer.capitalize()} application unknown. Try again with a valid application name")
print("===============================================================")
test()

Related

Why is request module closing after giving an input?

I am working on a project that finds if a user is available or not on Instagram, (Basically that's only one of the functions.)
To do that I use this code from requests:
def start():
clear() # Clears the previous input through the OS module
print(inp + cut + "Stress them is booting...") # Inp + Cut are optional strings
use = input("Who do you want to attack? Enter here: >> ") # We take the input from here (Specifically the user)
response = requests.get("https://www.instagram.com/"+xuse+"/") # Check if the user exists, this does not work if you put # in the beginning.
if response.status_code == 404 :
PrintFatalError("User could not be found, try again.") # The user wasn't found
# Here the program stops and returns to the main program / input where I ask the user for a command.
elif response.status_code == 200 :
PrintFatalError("User " + use + " has been detected ! Proceed with the tool? ") # The user was found
f = input(" ") # This is the point
if f in "y":
print ("Beginning")
else:
print("Not a valid option, aborting.") # I abort since I don't want a loop in this phase.
Some other info that might help:
The program is fully CLI, I don't use a GUI.
This program uses while loops instead of for loops, for many reasons.
NOTE: PrintFatalError is a variable I created to display messages in red / green color. It still does not work with the classic print("string") way through.

Python function returns inconsistent results

I wrote a script that lists EC2 instances in Amazon Web Services. It writes the results to confluence. But it's behaving oddly.
I'm on windows 10. The first time I open a powershell terminal and run it it reports the correct number of servers in the AWS account.
The next time I run it (without changing anything at all) it doubles the resutls. And each time you run it again with the same arguments it reports the same incorrect (doubled) amount.
This is the function that lists the instances and this is where I think the trouble is, but I'm having trouble finding it:
def list_instances(aws_account, aws_account_number, interactive, regions, fieldnames, show_details):
today, aws_env_list, output_file, output_file_name, fieldnames = initialize(interactive, aws_account)     options = arguments()     instance_list = ''     session = ''     ec2 = ''     account_found = ''     PrivateDNS = None     block_device_list = None     instance_count = 0     account_type_message = ''     profile_missing_message = ''     region = ''
# Set the ec2 dictionary
ec2info = {}
# Write the file headers
if interactive == 1:
with open(output_file, mode='w+') as csv_file:
writer = csv.DictWriter(csv_file, fieldnames=fieldnames, delimiter=',', lineterminator='\n')
            writer.writeheader()
if 'gov' in aws_account and not 'admin' in aws_account:
try:
session = boto3.Session(profile_name=aws_account,region_name=region)
account_found = 'yes'
except botocore.exceptions.ProfileNotFound as e:
message = f"An exception has occurred: {e}"
account_found = 'no'
banner(message)
else:
try:
session = boto3.Session(profile_name=aws_account,region_name=region)
account_found = 'yes'
except botocore.exceptions.ProfileNotFound as e:
message = f"An exception has occurred: {e}"
account_found = 'no'
banner(message)
print(Fore.CYAN)
report_gov_or_comm(aws_account, account_found)
print(Fore.RESET)
for region in regions:
if 'gov' in aws_account and not 'admin' in aws_account:
try:
session = boto3.Session(profile_name=aws_account,region_name=region)
except botocore.exceptions.ProfileNotFound as e:
profile_missing_message = f"An exception has occurred: {e}"                 account_found = 'no' pass else: try:                 session = boto3.Session(profile_name=aws_account,region_name=region)                 account_found = 'yes' except botocore.exceptions.ProfileNotFound as e:                 profile_missing_message = f"An exception has occurred: {e}" pass try:             ec2 = session.client("ec2") except Exception as e: pass
# Loop through the instances
try:
instance_list = ec2.describe_instances()
except Exception as e:
pass
try:
for reservation in instance_list["Reservations"]:
for instance in reservation.get("Instances", []):
instance_count = instance_count + 1
launch_time = instance["LaunchTime"]
launch_time_friendly = launch_time.strftime("%B %d %Y")
tree = objectpath.Tree(block_devices = set(tree.execute('$..BlockDeviceMappings['Ebs']['VolumeId']'))
if block_devices:
block_devices = list(block_devices)
block_devices = str(block_devices).replace('[','').replace(']','').replace("'",'')
else:
block_devices = None
private_ips =  set(tree.execute('$..PrivateIpAddress'))
if private_ips:
private_ips_list = list(private_ips)                         private_ips_list = str(private_ips_list).replace('[','').replace(']','').replace(''','')
else:
private_ips_list = None
type(private_ips_list)
public_ips =  set(tree.execute('$..PublicIp'))
if len(public_ips) == 0:
public_ips = None
if public_ips:
public_ips_list = list(public_ips)
public_ips_list = str(public_ips_list).replace('[','').replace(']','').replace("'",'')
else:
public_ips_list = None
if 'KeyName' in instance:
key_name = instance['KeyName']
else:
key_name = None
name = None
if 'Tags' in instance:
try:
tags = instance['Tags']
name = None
for tag in tags:
if tag["Key"] == "Name":
name = tag["Value"]
if tag["Key"] == "Engagement" or tag["Key"] == "Engagement Code":
engagement = tag["Value"]
except ValueError:
print("Instance: %s has no tags" % instance_id
pass
if 'VpcId' in instance:
vpc_id = instance['VpcId'] else:                         vpc_id = None if 'PrivateDnsName' in instance:                         private_dns = instance['PrivateDnsName'] else:                         private_dns = None if 'Platform' in instance:                         platform = instance['Platform'] else:                         platform = None print(f"Platform: {platform}")                     ec2info[instance['InstanceId']] = { 'AWS Account': aws_account, 'Account Number': aws_account_number, 'Name': name, 'Instance ID': instance['InstanceId'], 'Volumes': block_devices, 'Private IP': private_ips_list, 'Public IP': public_ips_list, 'Private DNS': private_dns, 'Availability Zone': instance['Placement']['AvailabilityZone'], 'VPC ID': vpc_id, 'Type': instance['InstanceType'], 'Platform': platform, 'Key Pair Name': key_name, 'State': instance['State']['Name'], 'Launch Date': launch_time_friendly                     } with open(output_file,'a') as csv_file:                         writer = csv.DictWriter(csv_file, fieldnames=fieldnames, delimiter=',', lineterminator='\n')                         writer.writerow({'AWS Account': aws_account, "Account Number": aws_account_number, 'Name': name, 'Instance ID': instance["InstanceId"], 'Volumes': block_devices,  'Private IP': private_ips_list, 'Public IP': public_ips_list, 'Private DNS': private_dns, 'Availability Zone': instance['Placement']['AvailabilityZone'], 'VPC ID': vpc_id, 'Type': instance["InstanceType"], 'Platform': platform, 'Key Pair Name': key_name, 'State': instance["State"]["Name"], 'Launch Date': launch_time_friendly})
if show_details == 'y' or show_details == 'yes': for instance_id, instance in ec2info.items(): if account_found == 'yes': print(Fore.RESET + "-------------------------------------") for key in [ 'AWS Account', 'Account Number', 'Name', 'Instance ID', 'Volumes', 'Private IP', 'Public IP', 'Private DNS', 'Availability Zone', 'VPC ID', 'Type', 'Platform', 'Key Pair Name', 'State', 'Launch Date'                                 ]: print(Fore.GREEN + f"{key}: {instance.get(key)}") print(Fore.RESET + "-------------------------------------") else: pass                     ec2info = {} with open(output_file,'a') as csv_file:                         csv_file.close() except Exception as e: pass if profile_missing_message == '*':         banner(profile_missing_message) print(Fore.GREEN)     report_instance_stats(instance_count, aws_account, account_found) print(Fore.RESET + '\n') return output_file
This is a paste of the whole code for context: aws_ec2_list_instances.py
The first time you run it from the command line it reports the correct total of servers in EC2 (can be verified in the AWS console):
----------------------------------------------------------
There are: 51 EC2 instances in AWS Account: company-lab.
----------------------------------------------------------
The next time it's run with ABSOLUTELY NOTHING changed it reports this total:
----------------------------------------------------------
There are: 102 EC2 instances in AWS Account: company-lab.
----------------------------------------------------------
You literally just up arrow the command and it doubles the results. When it writes to confluence you can see duplicate servers listed. It does that each time you up arrow to run it again, with the same incorrect total (102 servers).
If you close the powershell command line and open again it's back to reporting the correct result (51 servers) which corresponds to what you see in the AWS console.
What the heck is happening, here? Why is it doing that and how do I correct the problem?
This is pretty mysterious! I don't think I'm going to be able to debug it without access to your environment. My suggestion is that you use pdb to try to figure out how instance_count is being incremented past 51. I'd recommend adding import pdb; pdb.set_trace() at line 210, that is, right after for reservation in instance_list["Reservations"]:. You can then inspect the value of instance_count each time through the loop, see whether instance_list["Reservations"] actually has duplicate data somehow, etc.

How do I get the right string to work with Database connection

I am using python Qt and MySQLdb and I got this problem:
In this function
def connection(self,username,password):
try:
self.conn=MySQLdb.connect(host="localhost",user=username,passwd=password)
return True
except MySQLdb.Error:
return False
When I enter manually the username and password it goes well but when I try to get it from a Qt interface using:
str(pass_text.text())
it couldn't connect. When I tried:
print str(pass_text.text())
it does print the write string. I am confused... can you help me please?

Python's psutil module and a bizarre issue

This works perfectly:
def find_processes():
name = "ProcessName.exe"
pid_list = psutil.get_pid_list()
for pid in pid_list:
try:
if str(psutil.Process(pid).name()) == name:
return True
except:
pass
return False
This doesn't:
def find_processes():
name = "ProcessName.exe"
pid_list = psutil.get_pid_list()
for pid in pid_list:
if str(psutil.Process(pid).name()) == name:
return True
return False
It raises an error: AccessDenied: (pid=560)
I'm on a Windows environment and need to access all the processes' names. I already have a working code (the former), so my question is more out of curiosity.
What do the try/except statements do in the first example, and why is it not working if I remove them in the second?
Not all of the information from each process will be available to you unless you are the root user/administrator. See this question: python psutil on windows gives access denied.
You would be better off changing your first example to specifically catch these cases, with:
try:
if str(psutil.Process(pid).name()) == name:
return True
except AccessDenied:
print "Unable to access PID:",pid

Is there a way to detect whether a command prompt is available in python/django?

I have some code that will some times be run from a command line (django management command) and sometimes not (django changelist action). In this code, if a certain exception is raised, I can get some user input and keep going if the a command prompt (stdin) is available. Otherwise, I need to just let the exception propagate or do something different.
e.g.
def copy_account_settings(old_acct_domain, new_acct_domain):
try:
new_account = Account.objects.get(domain = new_acct_domain)
except Account.DoesNotExist:
print ("Couldn't find an account matching %s." % new_acct_domain)
if <command prompt is available>:
print "Would you like to create the account? (y/n)"
if raw_input().lower().strip()='y':
# get some more input and create the account and move on
else:
raise
How would you do this?
Perhaps you can check for a TTY?
import os
if os.isatty(0):
That should return true if the session is interactive and false if not.

Categories