Python cashier without db - python

so i have this mission to build a python cashier program using only python. without db use.
i use the dict and keys method to build it.
so i have 2 questions:
can i get an idea how to keep the program running after the moneybalance part, while i'm still saving the current moneybalance status? like, to make it an continuous program and not just one time.
i would like to get overall review on how is the idea for this mission, how it's written, and etc. would you do it in other way? if so i would like to hear how.
remember, my mission is to build python cashier without any outside libraries\db's.
Code:
print('welcome to python cashier')
money = int(input('enter cashier current money\n'))
prices = {"small popcorn" : 3, "medium popcorn" : 5,
"large popcorn" : 8, "small drink" : 1,
"medium drink" : 2, "large drink" : 3 }
def calc(money, prices):
try:
itemchange = pay - itemvalue
except Exception as e:
print(e)
finally:
print(f'change: {itemchange}')
def show(money, prices):
try:
for key,value in prices.items():
print (f'{key}: {value}')
except Exception as e:
print(e)
finally:
return False
show(money, prices)
def start(money, prices):
try:
for key, value in prices.items():
global item
item = str(input('enter what you want to buy:\n'))
if (item in prices.keys()):
global itemvalue
itemvalue = prices.get(item)
print(f'{item}: {itemvalue}')
global pay
pay = float(input('how much costumer pay?\n'))
return calc(money, prices)
else:
print('item not found')
except Exception as e:
print(e)
finally:
moneybalance = money + itemvalue
print(f'moneybalance: {moneybalance}')
start(money, prices)

The real question is if someone asked you to save the information. As you said they asked in the mission to do this without a database I don't think you need to do that. Btw if it's without an actual database you can use just .txt files to save information. Check about the "open" function in Python.
Quick Example:
with open('save.txt', 'w') as file:
file.write(str(cash)) # cash is an integer.
It's an example of writing a file. Btw I don't think they wanted you to save the information. Check it before you're applying something to don't ruin your work :).
I would suggest to put all the declarations of variables at the start of the script and add a "main" function. Call the main function from name == 'main'. Too I recommend you to do a more detailed function names. Try not to use global variables in this small code (you can declare it at the start, it'll be global and more easy to read your code and understand it faster). I think in your first question you thought about making your program run more than one time in any program run? Read about Python Loops if I'm correct :). Too you wrapped your input return with str() and it useless, because the returned value from input is already str (String type).
Quick Example:
# Variables Declaration (Just an example for the structure).
ABC = 0
cash = 1000
# Functions Declaration
def calculate_price(money, prices):
# Code Here.
pass
def main():
# The code of your start function, you don't need and arguments for this.
pass
if __name__ == '__main__':
main() # Call main here.
In this way your code will be readable and comfort to analyze :).

This sounds more like an assignment than an actual problem.
Here is the thing, and this is fundamental software architecture. You only need a database when it is time to persist something. So, what you need os a persistence service. Call it a database if you want, it can be as simple as a text file, as someone sugested.
Ironically the same set of rules that made your life easier as a developer, are making you confused. And questions arise. Specifically the question of what exactly happens when I close the program?
But the answer is dead simple. The requirements made it simple. If you close the application its gone. There is no persistence mechanism. This is actually super safe. No record, no proof. More importantly, its a requirement to be like so.
The problem, therefore, is you. You feel the need for persistence. You see an account and immediately place it in a database somewhere. You do a transaction, you feel the need to store it.
So what exactly happens when you persist something in a program? The program keeps all the information it needs to run. It may have gotten that information from a database, a user, or it may have randomly generated it. Who cares? All the program needs is the information in objects it knows how to use, in classes types and whatever more; in other words, in RAM. So persistence is taking things out of RAM into a less volatile storage.
But the real question is, how exactly does that affect the program? Does that cause any fundamental change?
For one the cashier operations are still the same. Prices must still be calculated, transactions must still be made, and all the rules associated must still be observed.
If something, there is less code involved. There is no solving the persistence problem. The information is volatile. Its a requirement to be so.
This is fundamentally the evolution process of a system under development, or even to some extent in production.
During development I care very little to store anything. What is actually usefull is to have reproucible state of the data. One I can interact with to make tests and verify that the software works (ie. it does not let me buy something if I have no money). This is easier done without any database system, specially the repoducible part.
Sure I can do backups of the data, but is it not easier to just restart the app? And where is the bug exactly if I need a specific database to see it? Is it in the code? Or is it a consistency issue in the database system? Probably the latter. How does that affect the cashier? It doesn't. Its a persistence detail. It has nothing to do with the business of a cashier.
I feel I have way more I could say, but I'm not sure where exactly you expect to get with this question. So I will stop here. Feel free to further inquire on this matter.

Related

Python : Handling an error by provoking it. Is this good practice?

I have a Python application for which I have a logger.
At different steps of the execution, the application must read various input files. Input files which can have different information but are all read through the same function.
One of the particular information I am looking at is one called computation_id and MUST be present in one of the file but can be absent from all others.
And I am interested to know what is a correct way of handling this situation. Currently I am handling it like this :
def input_reading(filename):
results = {}
[...]
try:
results['computation_id'] = read_computation_id()
except KeyError:
pass
[...]
return results
so if the computation_id is absent from the file being read, the code shall keep running. However, at some point, I will need this computation id and therefore I need to check if it was correctly read from the file where I expect to find it.
I actually need this value far down the code. But running the code up to this point (which takes some time) to then fail is wasted computation time. So my idea is to check for this value as soon as I can and handle the error the following way :
def specifc_file_read(filename):
[...]
results = input_reading('my_file')
try:
results['computation_id']
except KeyError:
logger.exception('no computation id provided, aborting')
raise SystemExit('no computation id provided, aborting')
[...]
Is this good practice ?
I have a feeling it's not since I need to write special code lines to check for the error "as soon as I can" in the code to avoid wasting computation time.
Since I don't have much experience with error handling, I want to know if this is good practice or not in order not to keep bad habits.
It comes down to what you prefer, imo.
I think that would be more readable
if 'computation_id' not in results: raise ...
although if you want to check if it's available in any file before you begin some heavy data processing, you could to
for f in get_files():
if 'computation_id' in f:
break
else:
raise SystemExit
So it will raise SystemExit if it didn't break, so if it's not available in at least one file.

Is it reasonable to wrap an entire main loop in a try..finally block?

I've made a map editor in Python2.7.9 for a small project and I'm looking for ways to preserve the data I edit in the event of some unhandled exception. My editor already has a method for saving out data, and my current solution is to have the main loop wrapped in a try..finally block, similar to this example:
import os, datetime #..and others.
if __name__ == '__main__':
DataMgr = DataManager() # initializes the editor.
save_note = None
try:
MainLoop() # unsurprisingly, this calls the main loop.
except Exception as e: # I am of the impression this will catch every type of exception.
save_note = "Exception dump: %s : %s." % (type(e).__name__, e) # A memo appended to the comments in the save file.
finally:
exception_fp = DataMgr.cwd + "dump_%s.kmap" % str(datetime.datetime.now())
DataMgr.saveFile(exception_fp, memo = save_note) # saves out to a dump file using a familiar method with a note outlining what happened.
This seems like the best way to make sure that, no matter what happens, an attempt is made to preserve the editor's current state (to the extent that saveFile() is equipped to do so) in the event that it should crash. But I wonder if encapsulating my entire main loop in a try block is actually safe and efficient and good form. Is it? Are there risks or problems? Is there a better or more conventional way?
Wrapping the main loop in a try...finally block is the accepted pattern when you need something to happen no matter what. In some cases it's logging and continuing, in others it's saving everything possible and quitting.
So you're code is fine.
If your file isn't that big, I would suggest maybe reading the entire input file into memory, closing the file, then doing your data processing on the copy in memory, this will solve any problems you have with not corrupting your data at the cost of potentially slowing down your runtime.
Alternatively, take a look at the atexit python module. This allows you to register a function(s) for a automatic callback function when the program exits.
That being said what you have should work reasonably well.

How to test while-loop (once) with nosetest (Python 2.7)

I'm pretty new to this whole "programming thing" but at age 34 I thought that I'd like to learn the basics.
I unfortunately don't know any python programmers. I'm learning programming due to personal interest (and more and more for the fun of it) but my "social habitat" is not "where the programmers roam" ;) .
I'm almost finished with Zed Shaws "Learn Python the Hard Way" and for the first time I can't figure out a solution to a problem. The last two days I didn't even stumble upon useful hints where to look when I repeatedly rephrased (and searched for) my question.
So stackoverflow seems to be the right place.
Btw.: I lack also the correct vocabular quite often so please don't hesitate to correct me :) . This may be one reason why I can't find an answer.
I use Python 2.7 and nosetests.
How far I solved the problem (I think) in the steps I solved it:
Function 1:
def inp_1():
s = raw_input(">>> ")
return s
All tests import the following to be able to do the things below:
from nose.tools import *
import sys
from StringIO import StringIO
from mock import *
import __builtin__
# and of course the module with the functions
Here is the test for inp_1:
import __builtin__
from mock import *
def test_inp_1():
__builtin__.raw_input = Mock(return_value="foo")
assert_equal(inp_1(), 'foo')
This function/test is ok.
Quite similar is the following function 2:
def inp_2():
s = raw_input(">>> ")
if s == '1':
return s
else:
print "wrong"
Test:
def test_inp_2():
__builtin__.raw_input = Mock(return_value="1")
assert_equal(inp_1(), '1')
__builtin__.raw_input = Mock(return_value="foo")
out = StringIO()
sys.stdout = out
inp_1()
output = out.getvalue().strip()
assert_equal(output, 'wrong')
This function/test is also ok.
Please don't assume that I really know what is happening "behind the scenes" when I use all the stuff above. I have some layman-explanations how this is all functioning and why I get the results I want but I also have the feeling that these explanations may not be entirely true. It wouldn't be the first time that how I think sth. works turns out to be different after I've learned more. Especially everything with "__" confuses me and I'm scared to use it since I don't really understand what's going on. Anyway, now I "just" want to add a while-loop to ask for input until it is correct:
def inp_3():
while True:
s = raw_input(">>> ")
if s == '1':
return s
else:
print "wrong"
The test for inp_3 I thought would be the same as for inp_2 . At least I am not getting error messages. But the output is the following:
$ nosetests
......
# <- Here I press ENTER to provoke a reaction
# Nothing is happening though.
^C # <- Keyboard interrupt (is this the correct word for it?)
----------------------------------------------------------------------
Ran 7 tests in 5.464s
OK
$
The other 7 tests are sth. else (and ok).
The test for inp_3 would be test nr. 8.
The time is just the times passed until I press CTRL-C.
I don't understand why I don't get error- or "test failed"-meassages but just an "ok".
So beside the fact that you may be able to point out bad syntax and other things that can be improved (I really would appreciate it, if you would do this), my question is:
How can I test and abort while-loops with nosetest?
So, the problem here is when you call inp_3 in test for second time, while mocking raw_input with Mock(return_value="foo"). Your inp_3 function runs infinite loop (while True) , and you're not interrupting it in any way except for if s == '1' condition. So with Mock(return_value="foo") that condition is never satisfied, and you loop keeps running until you interrupt it with outer means (Ctrl + C in your example). If it's intentional behavior, then How to limit execution time of a function call in Python will help you to limit execution time of inp_3 in test. However, in cases of input like in your example, developers often implement a limit to how many input attempts user have. You can do it with using variable to count attempts and when it reaches max, loop should be stopped.
def inp_3():
max_attempts = 5
attempts = 0
while True:
s = raw_input(">>> ")
attempts += 1 # this is equal to "attempts = attempts + 1"
if s == '1':
return s
else:
print "wrong"
if attempts == max_attempts:
print "Max attempts used, stopping."
break # this is used to stop loop execution
# and go to next instruction after loop block
print "Stopped."
Also, to learn python I can recommend book "Learning Python" by Mark Lutz. It greatly explains basics of python.
UPDATE:
I couldn't find a way to mock python's True (or a builtin.True) (and yea, that sounds a bit crazy), looks like python didn't (and won't) allow me to do this. However, to achieve exactly what you desire, to run infinite loop once, you can use a little hack.
Define a function to return True
def true_func():
return True
, use it in while loop
while true_func():
and then mock it in test with such logic:
def true_once():
yield True
yield False
class MockTrueFunc(object):
def __init__(self):
self.gen = true_once()
def __call__(self):
return self.gen.next()
Then in test:
true_func = MockTrueFunc()
With this your loop will run only once. However, this construction uses a few advanced python tricks, like generators, "__" methods etc. So use it carefully.
But anyway, generally infinite loops considered to be bad design solutions. Better to not getting used to it :).
It's always important to remind me that infinite loops are bad. So thank you for that and even more so for the short example how to make it better. I will do that whenever possible.
However, in the actual program the infinite loop is how I'd like to do it this time. The code here is just the simplified problem.
I very much appreciate your idea with the modified "true function". I never would have thought about that and thus I learned a new "method" how tackle programming problems :) .
It is still not the way I would like to do it this time, but this was the so important clue I needed to solve my problem with existing methods. I never would have thought about returning a different value the 2nd time I call the same method. It's so simple and brilliant it's astonishing me :).
The mock-module has some features that allows a different value to be returned each time the mocked method is called - side effect .
side_effect can also be set to […] an iterable.
[when] your mock is going to be
called several times, and you want each call to return a different
value. When you set side_effect to an iterable every call to the mock
returns the next value from the iterable:
The while-loop HAS an "exit" (is this the correct term for it?). It just needs the '1' as input. I will use this to exit the loop.
def test_inp_3():
# Test if input is correct
__builtin__.raw_input = Mock(return_value="1")
assert_equal(inp_1(), '1')
# Test if output is correct if input is correct two times.
# The third time the input is corrct to exit the loop.
__builtin__.raw_input = Mock(side_effect=['foo', 'bar', '1'])
out = StringIO()
sys.stdout = out
inp_3()
output = out.getvalue().strip()
# Make sure to compare as many times as the loop
# is "used".
assert_equal(output, 'wrong\nwrong')
Now the test runs and returns "ok" or an error e.g. if the first input already exits the loop.
Thank you very much again for the help. That made my day :)

Python, How to swap between multiple infinite loops?

Could someone please point me in the right direction?
I am trying to swap between multiple infinite control loops within python. I need to kill a loop and then select a different loop upon request from an outside source(hopefully web interface), not based on an internal condition. I understand this is a vague question but I need a general point in the right direction to get me started, I have looked at exceptions, signals and threading but I am struggling to find what would be the "correct" way to do this.
Please note, I work in electronics not programming so sorry if this sounds stupid. Also if this is completely the wrong way to go about the problem could someone advise me on the correct method.
I can provide more info/explanation if someone can help me and post code if needed but I think it's pretty irrelevant at the moment due to the vagueness of the question.
Thanks
I'm guessing you have two (or more) procedures you want to run repeatedly and allow them to be changed when the user selects a new condition. I would take advantage of Python having functions as objects and so something like this:
def f1():
# do something
def f2():
# do something else
func_to_run = {"user_input1": f1, "user_input2": f2}
while True:
user_input = get_any_new_input() # however you want to get your user input
func_to_run[user_input]()
Edit: As Keith mentioned in the comments, get_any_new_input needs to be non-blocking. I would do this via threading. The web interface should be on a separate thread from the loops, but share a control object that the web interface will set. This could be a table in a database if you have that available. It might look something like this if you use your own lock:
L = threading.Lock() # Shared by web ui
user_response = 'data set by web ui'
last_input = 'user_input1'
def get_any_new_input(L, last_input, user_response):
if L.acquire([False]):
last_input = user_response
return last_input
The easiest way is probably just read some file which controls your loops ...
while True:
#loop1
while True:
#do something
with open("some.file") as f:
if f.read() == "loop2":
break
#loop2
while True:
#do something
with open("some.file") as f:
if f.read() == "loop1":
break
then just put which loop you want in "some.file" (however you want ... web interface etc)

Return continuous result from a single function call

I have got stuck with a problem.
It goes like this,
A function returns a single result normally. What I want is it to return continuous streams of result for a certain time frame(optional).
Is it feasible for a function to repeatedly return results for a single function call?
While browsing through the net I did come across gevent and threading. Will it work if so any heads up how to solve it?
I just need to call the function carry out the work and return results immediately after every task is completed.
Why you need this is not specified in the question, so it is hard to know what you need, but I will give you a general idea, and code too.
You could return in that way: return var1, var2, var3 (but that's not what you need I think)
You have multiple options: either blocking or non-blocking. Blocking means your code will no longer execute while you are calling the function. Non-blocking means that it will run in parallel. You should also know that you will definitely need to modify the code calling that function.
That's if you want it in a thread (non-blocking):
def your_function(callback):
# This is a function defined inside of it, just for convenience, it can be any function.
def what_it_is_doing(callback):
import time
total = 0
while True:
time.sleep(1)
total += 1
# Here it is a callback function, but if you are using a
# GUI application (not only) for example (wx, Qt, GTK, ...) they usually have
# events/signals, you should be using this system.
callback(time_spent=total)
import thread
thread.start_new_thread(what_it_is_doing, tuple(callback))
# The way you would use it:
def what_I_want_to_do_with_each_bit_of_result(time_spent):
print "Time is:", time_spent
your_function(what_I_want_to_do_with_each_bit_of_result)
# Continue your code normally
The other option (blocking) involves a special kind of functions generators which are technically treated as iterators. So you define it as a function and acts as an iterator. That's an example, using the same dummy function than the other one:
def my_generator():
import time
total = 0
while True:
time.sleep(1)
total += 1
yield total
# And here's how you use it:
# You need it to be in a loop !!
for time_spent in my_generator():
print "Time spent is:", time_spent
# Or, you could use it that way, and call .next() manually:
my_gen = my_generator()
# When you need something from it:
time_spent = my_gen.next()
Note that in the second example, the code would make no sense because it is not really called at 1 second intervals, because there's the other code running each time it yields something or .next is called, and that may take time. But I hope you got the point.
Again, it depends on what you are doing, if the app you are using has an "event" framework or similar you would need to use that, if you need it blocking/non-blocking, if time is important, how your calling code should manipulate the result...
Your gevent and threading are on the right track, because a function does what it is programmed to do, either accepting 1 var at a time or taking a set and returning either a set or a var. The function has to be called to return either result, and the continuous stream of processing is probably taking place already or else you are asking about a loop over a kernel pointer or something similar, which you are not, so ...
So, your calling code which encapsulates your function is important, the function, any function, eg, even a true/false boolean function only executes until it is done with its vars, so there muse be a calling function which listens indefinitely in your case. If it doesn't exist you should write one ;)
Calling code which encapsulates is certainly very important.
Folks aren't going to have enough info to help much, except in the super generic sense that we can tell you that you are or should be within in some framework's event loop, or other code's loop of some form already- and that is what you want to be listening to/ preparing data for.
I like "functional programming's," "map function," for this sort of thing. I think. I can't comment at my rep level or I would restrict my speculation to that. :)
To get a better answer from another person post some example code and reveal your API if possible.

Categories

Resources