Display an error message when argument not there - python

I have a directory where csv files are located. The code reads the files and creates histograms based on the data in the files.
I have made this a command prompt code where I can enter the arguments and the code will look through the csv files to see if the arguments I listed are there. I am trying to make it so that an error message comes up when I misspell a command. The following code works if the first argument is spelled correctly and the second is not, but does not display an error message if the first is misspelled and the second is correct. What's wrong?
Example: python untitled14.py "Folder" Are Perimeter DOES NOT DISPLAY ERROR MESSAGE FOR ARE
BUT python untitled14.py "Folder" Perimeter Are DOES DISPLAY ERROR FOR ARE
for x in arguments:
found_match = False
for column in df:
os.chdir(directory)
if x.endswith(column):
found_match = True
#histogram code
continue
else:
pass
if found_match==False:
print files+" " + x + " does not exist"

You have unnecessary things (and some other questionable things) in your loop logic. For example, the three lines continue; else: pass do literal nothing.
The best thing to do would be to refactor your code to call a function that would return True if all the arguments validated. You didn't provide enough code for that, so I would clean the whole thing up with:
for x in arguments:
for column in df:
os.chdir(directory)
if x.endswith(column):
#histogram code
break
else:
print "{0} {1} does not exist".format(files,x)
break #or not, depending on what you want to do
This takes advantage of the somewhat rarely-used for/else to do something if the for loop did not break - which, in your case, is an error.
If you want to really make this re-usable, you should raise an Exception instead of just printing on an error.

Related

Python-How to execute code and store into variable?

So I have been struggling with this issue for what seems like forever now (I'm pretty new to Python). I am using Python 3.7 (need it to be 3.7 due to variations in the versions of packages I am using for the project) to develop an AI chatbot system that can converse with you based on your text input. The program reads the contents of a series of .yml files when it starts. In one of the .yml files I am developing a syntax for when the first 5 characters match a ^###^ pattern, it will instead execute the code and return the result of that execution rather than just output text back to the user. For example:
Normal Conversation:
- - What is AI?
- Artificial Intelligence is the branch of engineering and science devoted to constructing machines that think.
Service/Code-based conversation:
- - Say hello to me
- ^###^print("HELLO")
The idea is that when you ask it to say hello to you, the ^##^print("HELLO") string will be retrieved from the .yml file, the first 5 characters of the response will be removed, the response will be sent to a separate function in the python code where it will run the code and store the result into a variable which will be returned from the function into a variable that will give the nice, clean result of HELLO to the user. I realize that this may be a bit hard to follow, but I will straighten up my code and condense everything once I have this whole error resolved. As a side note: Oracle is just what I am calling the project. I'm not trying to weave Java into this whole mess.
THE PROBLEM is that it does not store the result of the code being run/executed/evaluated into the variable like it should.
My code:
def executecode(input):
print("The code to be executed is: ",input)
#note: the input may occasionally have single quotes and/or double quotes in the input string
result = eval("{}".format(input))
print ("The result of the code eval: ", result)
test = eval("2+2")
test
print(test)
return result
#app.route("/get")
def get_bot_response():
userText = request.args.get('msg')
print("Oracle INTERPRETED input: ", userText)
ChatbotResponse = str(english_bot.get_response(userText))
print("CHATBOT RESPONSE VARIABLE: ", ChatbotResponse)
#The interpreted string was a request due to the ^###^ pattern in front of the response in the custom .yml file
if ChatbotResponse[:5] == '^###^':
print("---SERVICE REQUEST---")
print(executecode(ChatbotResponse[5:]))
interpreter_response = executecode(ChatbotResponse[5:])
print("Oracle RESPONDED with: ", interpreter_response)
else:
print("Oracle RESPONDED with: ", ChatbotResponse)
return ChatbotResponse
When I run this code, this is the output:
Oracle INTERPRETED input: How much RAM do you have?
CHATBOT RESPONSE VARIABLE: ^###^print("HELLO")
---SERVICE REQUEST---
The code to be executed is: print("HELLO")
HELLO
The result of the code eval: None
4
None
The code to be executed is: print("HELLO")
HELLO
The result of the code eval: None
4
Oracle RESPONDED with: None
Output on the website interface
Essentially, need it to say HELLO for the "The result of the code eval:" output. This should get it to where the chatbot responds with HELLO in the web interface, which is the end goal here. It seems as if it IS executing the code due to the HELLO's after the "The code to be executed is:" output text. It's just not storing it into a variable like I need it to.
I have tried eval, exec, ast.literal_eval(), converting the input to string with str(), changing up the single and double quotes, putting \ before pairs of quotes, and a few other things. Whenever I get it to where the program interprets "print("HELLO")" when it executes the code, it complains about the syntax. Also, from several days of looking online I have figured out that exec and eval aren't generally favored due to a bunch of issues, however I genuinely do not care about that at the moment because I am trying to make something that works before I make something that is good and works. I have a feeling the problem is something small and stupid like it always is, but I have no idea what it could be. :(
I used these 2 resources as the foundation for the whole chatbot project:
Text Guide
Youtube Guide
Also, I am sorry for the rather lengthy and descriptive question. It's rare that I have to ask a question of my own on stackoverflow because if I have a question, it usually already has a good answer. It feels like I've tried everything at this point. If you have a better suggestion of how to do this whole system or you think I should try approaching this another way, I'm open to ideas.
Thank you for any/all help. It is very much appreciated! :)
The issue is that python's print() doesn't have a return value, meaning it will always return None. eval simply evaluates some expression, and returns back the return value from that expression. Since print() returns None, an eval of some print statement will also return None.
>>> from_print = print('Hello')
Hello
>>> from_eval = eval("print('Hello')")
Hello
>>> from_print is from_eval is None
True
What you need is a io stream manager! Here is a possible solution that captures any io output and returns that if the expression evaluates to None.
from contextlib import redirect_stout, redirect_stderr
from io import StringIO
# NOTE: I use the arg name `code` since `input` is a python builtin
def executecodehelper(code):
# Capture all potential output from the code
stdout_io = StringIO()
stderr_io = StringIO()
with redirect_stdout(stdout_io), redirect_stderr(stderr_io):
# If `code` is already a string, this should work just fine without the need for formatting.
result = eval(code)
return result, stdout_io.getvalue(), stderr_io.getvalue()
def executecode(code):
result, std_out, std_err = executecodehelper(code)
if result is None:
# This code didn't return anything. Maybe it printed something?
if std_out:
return std_out.rstrip() # Deal with trailing whitespace
elif std_err:
return std_err.rstrip()
else:
# Nothing was printed AND the return value is None!
return None
else:
return result
As a final note, this approach is heavily linked to eval since eval can only evaluate a single statement. If you want to extend your bot to multiple line statements, you will need to use exec, which changes the logic. Here's a great resource detailing the differences between eval and exec: What's the difference between eval, exec, and compile?
It is easy just convert try to create a new list and add the the updated values of that variable to it, for example:
if you've a variable name myVar store the values or even the questions no matter.
1- First declare a new list in your code as below:
myList = []
2- If you've need to answer or display the value through myVar then you can do like below:
myList.append(myVar)
and this if you have like a generator for the values instead if you need the opposite which means the values are already stored then you will just update the second step to be like the following:
myList[0]='The first answer of the first question'
myList[1]='The second answer of the second question'
ans here all the values will be stored in your list and you can also do this in other way, for example using loops is will be much better if you have multiple values or answers.

Search in text file by date

I have code like this:
from datetime import datetime
from tabulate import tabulate
def search_projection_date():
projections = open('projections.txt','r').readlines()
date = input("Input projection date: ")
try:
date = date.strptime(date, "%d.%m.%Y.")
except:
print("Date input error!")
#search_projection_date()
for i in projections:
projections = i.strip("\n").split("|")
if date == projections[2]:
table = [['Code:',projections[0]],['Hall:',projections[1]],['Date:',projections[2]],['Start time:',projections[3]],['End time:', projections[4]],['Day(s):', projections[5]], ['Movie:', projections[6]], ['Price:', projections[7]]]
print (tabulate(table))
#break
else:
print("No projection on that date")
And text file like this:
0001|AAA|17.12.2017.|20:30|21:00|sunday|For a few dolars more|150
0002|BBB|17.12.2017.|19:30|21:15|saturday|March on the Drina|300
0003|GGG|19.12.2017.|18:00|19:00|tuesday|A fistful of Dolars|500
0004|GGG|16.12.2017.|21:15|00:00|sunday|The Good, the Bad and the Ugly|350
I try to search movie projections by date...
If there is a projection on the entered date it will find it and print the list, but before printing that list it will always print "Date input error" and after that list "No projection on that date". (if I put break in if statement it will print only the first found projection on entered day, withouth else statement, obvious)
Questions: How to print ONLY list of projections without "date input error" if date is correctly input.
How to print only "No projection on that date" if date is correct but there is no projection and how to ask user for input that until puts it correctly? In this way with recursion it will always throw exception and recursion search_projection_date() function.
There are a whole bunch of major problems with your code. As it happens, they showcase why some general advice we hear so often is actually good advice.
The line date = input("Input projection date: ") creates a string named date. input always returns a string. Strings in Python do not have a method called strptime. Which brings us to issue #2:
You should not catch generic exceptions. You were probably looking to trap a TypeError or ValueError in the except clause. However, you are getting an error that says AttributeError: 'str' object has no attribute 'strptime'. This is because you can't call methods that you want to exist but don't. Your except line should probably read something like except ValueError:.
Your except clause does nothing useful (beyond the problems listed above). If the string is not formatted correctly, you print a message but continue anyway. You probably want to use raise in the except clause to propagate the exception further. Luckily for you, you actually want the date to be a string, which brings us to issue #4:
Why are you attempting to convert the string to a date to begin with? You can not compare a date object and a string that you get from the file and ever expect them to be equal. You want to compare a string to a string. If you had some kind of validation in mind, that's fine, but use datetime.strptime and don't replace the original string; just raise an error if it doesn't convert properly.
The else clause in a for loop will execute whenever the loop terminates normally (i.e., without a break). Since you always iterate through all the lines, you will always trigger the else clause. You need to have another way to determine if you found matching items, like a boolean flag or a counter. I will show an example with a counter, since it is more general.
You never close your input file. Not a huge problem in this tiny example, but can cause major issues with bigger programs. Use a with block instead of raw open.
Your method of iterating through the file is not wrong per-se, but is inefficient. You load the entire file into memory, and then iterate over the lines. In Python, text files are already iterable over the lines, which is much more efficient since it only loads one line at a time into memory, and also doesn't make you process the file twice.
Combining all that, you can make your code look like this:
def search_projection_date():
counter = 0
with open('projections.txt','r') as projections:
date = input("Input projection date: ")
for line in projections:
projection = line.strip("\n").split("|")
if date == projection[2]:
table = [['Code:',projection[0]],
['Hall:',projection[1]],
['Date:',projection[2]],
['Start time:',projection[3]],
['End time:', projection[4]],
['Day(s):', projection[5]],
['Movie:', projection[6]],
['Price:', projection[7]]]
print(tabulate(table))
counter += 1
if not counter:
print("No projection on that date")
else:
print("Found {0} projections on {1}".format(counter, date))
I trusted your use of tabulate since I am not familiar with the module and have no intention of installing it. Keep in mind that the date verification is optional. If the user enters an invalid string, that's the end of it: you don't need to check for dates like 'aaaa' because they will just print No projection on that date. If you insist on keeping the verification, do it more like this:
from datetime import datetime
datetime.strftime(date, '%d.%m.%Y.')
That's it. It will raise a ValueError if the date does not match. You don't need to do anything with the result. If you want to change the error message, or return instead of raising an error, you can catch the exception:
try:
datetime.strftime(date, '%d.%m.%Y.')
except ValueError:
print('Bad date entered')
return
Notice that I am catching a very specific type of exception here, not using a generic except clause.

Program doesn't append file using variables, but no error message appears

Using Python 3.4.2
I'm working on a quiz system using python. Though it hasn't been efficient, it has been working till now.
Currently, I have a certain user log in, take a quiz, and the results of the quiz get saved to a file for that users results. I tried adding in so that it also saves to a file specific to the subject being tested, but that's where the problem appears.
user_score = str(user_score)
user_score_percentage_str = str(user_score_percentage)
q = open('user '+(username)+' results.txt','a')
q.write(test_choice)
q.write('\n')
q.write(user_score+'/5')
q.write('\n')
q.write(user_score_percentage_str)
q.write('\n')
q.write(user_grade)
q.write('\n')
q.close()
fgh = open(test_choice+'results.txt' ,'a')
fgh.write(username)
fgh.write('\n')
fgh.write(user_score_percentage_str)
fgh.write('\n')
fgh.close
print("Your result is: ", user_score , "which is ", user_score_percentage,"%")
print("Meaning your grade is: ", user_grade)
Start()
Everything for q works (this saves to the results of the user)
However, once it comes to the fgh, the thing doesn't work at all. I receive no error message, however when I go the file, nothing ever appears.
The variables used in the fgh section:
test_choice this should work, since it worked for the q section
username, this should also work since it worked for the q section
user_score_percentage_str and this, once more, should work since it worked for the q section.
I receive no errors, and the code itself doesn't break as it then correctly goes on to print out the last lines and return to Start().
What I would have expected in the file is to be something like:
TestUsername123
80
But instead, the file in question remains blank, leading me to believe there must be something I'm missing regarding working the file.
(Note, I know this code is unefficient, but except this one part it all worked.)
Also, apologies if there's problem with my question layout, it's my first time asking a question.
And as MooingRawr kindly pointed out, it was indeed me being blind.
I forgot the () after the fgh.close.
Problem solved.

Python "In" Comparison with *$("!£*!'. characters

Seems while learning as I'm going with Python that I'm running into every little roadblock I can.
Even though this is a simply "if" I can't seem to get it to work, and i was wondering if its because my input (pgName) has full stops within the string. e.g com.android.driver.software.
In my example scenario, I will enter com.android.driver.software, what is listed within the Dict.value is com.android.driver.software.7 I thought using the comparison "in" would work in this instance, but it doesn't seem to be handling the logic at all.. What am i doing wrong?
pgName = raw_input("Please enter a package name e.g com.android.driver.software: ")
#while loop that checks user input from pgName to see if it matches any device
#listed in the JSON output and if so printing all the entires for that value.
while True:
try:
jdata = data["result"]["items"][y]["tagValues"]["IdDevicesMap"]["value"]
for device in jdata.values():
if pgName in device:
print jdata[device]
print " "
else:
print 'false'
When i run it everything is false.

Code Stuck in a Loop and Need to Strip Characters from a File

I am trying to code a program that asks the user what the value of a variable is, opens a file, searches for a word, and then checks to see if the number after that word is equal to the user inputted variable, which means I have to get rid of the spaces in between that specific word and the number after it. Unfortunately, I am having some problems with my code and can’t figure out why it will not work. I am sorry if the question I am asking is fairly simple, I haven't coded in python in over a year and am extremely rusty to say the least.
def getword1(prompt):
while True:
filestr1 = input(prompt)
def getword2(prompt):
while True:
filestr2 = input(prompt)
def getword3(prompt):
while True:
filestr3 = input(prompt)
def openfile(prompt, missingfileerror):
"""Opens a file"""
while True:
try:
filestr = input(prompt)
return open(filestr)
except FileNotFoundError:
print(missingfileerror)
uservariable1 = getword1("What is the value of the first variable? If not applicable, please enter 0")
variable1search = ("Word1", uservariable1)
uservariable2 = getword2("What is the value of the second variable? If not applicable, please enter 0")
variable2search = ("Word2", uservariable2)
uservariable3 = getword3("What is the value of the third variable? If not applicable, please enter 0")
variable3search = ("Word3", uservariable3)
file = openfile("Enter the name of the file that contains the variables.")
if uservariable1 == ("0"):
print("No uservariable1")
else:
if variable1search in file:
print("The variable values match.")
else:
print("The variable values do not match.")
if uservariable2 == ("0"):
print("No uservariable2")
else:
if variable2search in file:
print("The variable values match.")
else:
print("The variable values do not match.")
if uservariable3 == ("0"):
print("No uservariable3")
else:
if variable3search in file:
print("The variable values match.")
else:
print("The variable values do not match.")
file.close()
When I run the code in terminal, the code asks my first question, but after I give it an answer, it is stuck in a loop of asking me the same first question over and over again. I also cannot remember how to properly use the .strip() function in this instance. I am searching for a string as my variable because the value of the variable will include a comma, such as 750,000 or 2,000. If I can strip the comma and also maybe a $ sign from the opened file, I would be able to search for an int instead of a string. Thanks for your time!
Remove the while loop from the openfile function. It has no use.
def openfile(prompt, missingfileerror):
"""Opens a file"""
try:
filestr = input(prompt)
return open(filestr)
except FileNotFoundError:
print(missingfileerror)
NB. One other slight problem with your setup is that you should always close files that you've opened. But in this function, you cannot do that anymore, because the code after return will not be executed (if there are no errors).
Another problem is that your code is not DRY (look up the principle). You've duplicated many functions that are almost identical. There is probably a way to do this in 1/3 of the code.
Another problem is that you have added while loops in getword<x> as well, they are not needed either.
To answer your first point, the code is getting stuck asking the first question repeatedly because of your while True in getword1().
There is an also an awful lot wrong with the rest of your code:
Unnecessary while loops everywhere
You don't return anything from your getword() functions, (so uservariable1 etc. will end up as None)
You don't need 3 separate getword() functions, one would do
Actually, you don't really need any, (if you're not going to do any validation), you could just write uservariable1 = input("What is the value ...") etc.
if variable2search in file will never return True - you need to iterate over the file's contents
If you do want to do some user input validation, you could try something like:
def getword(prompt):
while True:
foo = input(prompt)
if <some evaluation criteron here>:
return foo #Return input and break out of while loop
I suggest reading up on while and file access, as a minimum.
Finally, try writing your code in small chunks and proving each bit works before moving on to the next, it's easier to debug that way.

Categories

Resources