Python, How to swap between multiple infinite loops? - python

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)

Related

trio.Event(): Which is “better”: setting and initializing a new Event or checking if someone is waiting for it beforehand?

import trio
work_available = trio.Event()
async def get_work():
while True:
work = check_for_work()
if not work:
await work_available.wait()
else:
return work
def add_work_to_pile(...):
...
if work_available.statistics().tasks_waiting:
global work_available
work_available.set()
work_available = trio.Event()
In this Python-like code example I get work in bursts via add_work_to_pile(). The workers which get work via get_work() are slow. So most of the time add_work_to_pile() is called there will be no one waiting on work_available.
Which is better/cleaner/simpler/more pythonic/more trionic/more intended by the trio developers?
checking if someone is looking for the Event() via statistics().tasks_waiting, like in the example code, ...or...
unconditionally set() setting the Event() and creating a new one each time? (Most of them in vain.)
Furthermore... the API does not really seem to expect regular code to check if someone is waiting via this statistics() call...
I don’t mind spending a couple more lines to make things clearer. But that goes both ways: a couple CPU cycles more are fine for simpler code...
Creating a new Event is roughly the same cost as creating the _EventStatistics object within the statistics method. You'll need to profile your own code to pick out any small difference in performance. However, although it is safe and performant, the intent of statistics across trio's classes is for debug rather than core logic. Using/discarding many Event instances would be relatively more along the intent of the devs.
A more trionic pattern would be to load each work item into a buffered memory channel in place of your add_work_to_pile() method and then iterate on that in the task that awaits get_work. I feel the amount of code is comparable to your example:
import trio
send_chan, recv_chan = trio.open_memory_channel(float('inf'))
async def task_that_uses_work_items():
# # compare
# while True:
# work = await get_work()
# handle_work(work)
async for work in recv_chan:
handle_work(work)
def add_work_to_pile():
...
for work in new_work_set:
send_chan.send_nowait(work)
# maybe your work is coming in from a thread?
def add_work_from_thread():
...
for work in new_work_set:
trio_token.run_sync_soon(send_chan.send_nowait, work)
Furthermore, it's performant because the work items are efficiently rotated through a deque internally. This code would checkpoint for every work item so you may have to jump through some hoops if you want to avoid that.
I think you might want a trio.ParkingLot. It gives more control over parking (i.e. which is like Event.wait()) and unparking (which is like Event.set() except that it doesn't stop future parkers from waiting). But it doesn't have any notion of being set at all so you would need to store that information separately. If you work is naturally Truety when set (e.g. a non-empty list) then that might be easy anyway. Example:
available_work = []
available_work_pl = trio.ParkingLot()
async def get_work():
while not available_work:
await available_work_pl.park()
result = list(available_work)
available_work.clear()
return result
def add_work_to_pile():
available_work.append(foo)
available_work_pl.unpark()
Edit: Replaced "if" with "while" in get_work(). I think if has a race condition: if there are two parked tasks and then add_work_to_pile() gets called twice, then one get_work() would get both work items but the other would still be unparked and return an empty list. Using while instead will make it loop back around until more data is added.
IMHO you don't want an event in the first place. The combination of an array and something that tells the reader there's work in the array is already available as memory channels. They have the additional advantage that you can tell them how much work to accept before the sender stalls.
send_channel, recv_channel = trio.open_memory_channel(10)
get_work = recv_channel.receive
add_work_to_pile = send_channel.send
# both are async functions or use the _nowait() versions

Python cashier without db

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.

How to implement an asynchronous function in python 3

I'm very new to programming as a whole. Had some basic experience with C++ and HTML, like simple calculators and other really basic stuff(I started learning on my own a few months ago) and because of this I'm not even sure if I am posting this question correctly. Maybe it goes without saying but I am new to stackoverflow as well(My first post!), so I may do some things wrong here and I kindly ask for your comprehension. Any constructive criticism is more than welcome!
So here's my problem: I am trying to make a simple chatting program in Python 3, but here's the catch: I want to use python's asychronous capabilities to allow the user to terminate the program at any given time the esc key is pressed. I've looked into a few libraries already, such as pynput, asyncio, tornado and getch(). But no matter how I change my code I just can't seem to reach my goal here.
I made an async function called runalways() that's supposed to run during the entire duration of the program, parallel to the other functions. But it doesn't and I couldn't figure out why...
I'm sorry if I couldn't explain my issue properly. Some terms and concepts are still rather blurry to me, but hopefully it won't be so for long. I'll leave the code I have so far which does a good job implementing the chat function, but that's about it. The async bit is basically inexistent at this moment.
It would be really appreciated if someone could explain what I'm missing:
import time, asyncio
from msvcrt import getch
# Creates a chat-like effect
def typing(text):
for i in text:
print(i, end=" ")
time.sleep(0.1)
time.sleep(1.0)
# Terminates the program
def termination():
print("Program terminated")
time.sleep(0.5)
SystemExit
# Defines async function to read pressed keys and terminate if Esc is pressed
# (Not working)
async def runalways():
while True:
print(ord(getch()))
key = ord(getch())
if key == 27: # Esc
termination()
# Initialize chatting
def startChat():
typing("\nHello!\n")
typing("How are you?\n\n")
typing("Answer:\t")
x = input()
typing("\nAnyways, that isn't relevant right now.\n")
time.sleep(0.5)
typing("Can we get started?\n\n")
typing("Answer(Y/N):\t")
x = input()
# validates input
while (x != "Y") & (x != "N"):
typing("\nHey, don't go fooling around now. Keep it real! Try again.\n\n")
typing("Answer(Y/N):\t")
x = input()
if (x == "Y") | (x == "y"):
typing("\nThere you go! Now, let's go through the basics...\n\n")
termination()
elif (x == "N") | (x == "n"):
typing("\nSorry to hear that... See you next time, then!")
termination()
# Defines starter point for the program
def main():
runalways()
startChat()
main()
I will try my best to clarify any questions that may help the understanding of my issue. Thanks in advance!
You have two functions competing to grab the input. runalways wants to grab them with getch, while your main chat loop is trying with input. The two processes conflict; only one can consume each character. Whenever one thread grabs input, the other gets to claim the buffer for the next input.
Instead, you need to set up a single input channel that terminates immediately on ESC; otherwise, it echoes to the terminal and passes the character to the main loop (or buffers it until EOL appears).

How can I conduct a poll through an irc bot?

I've set up a irc bot using socket. I've added a few commands , but I'd like to add a "poll" function.
Ideally, the bot would get a command with this format:
!poll <name> <opt1> <opt2> <opt3> <time>
How would I go about checking user who voted and ending the poll after a certain time?
Thanks in advance,
Desperate Python Beginner.
EDIT: Thanks a lot for the responses guys, I went with using global vars ( I know, I know ) because I couldn't figure out how to do it otherwise. Again, thanks a lot!
Well, I'm starting to get a little rusty with my Python but I think I can answer that - It may not be the best answer, though.
If you plan to have many polls going at once, you could implement a dictionary containing multiple instances of a custom class like Poll.. Here's a possible solution:
class PollVotes(object):
def __init__(self):
self.votes = []
self.stoptime = "some date/time" #I can't remember how to do this bit ;)
def add_vote(self, vote_value):
self.votes.append(vote_value);
def tally_votes(self):
return self.votes.size()
def has_closed(self):
if time_now >= self.stoptime: # I forget how you'd do this exactly, but it's for sake of example
return True
else:
return False
#then use it something like this
poll_list = {}
#irc processing...
if got_vote_command:
if poll_list["channel_or_poll_name"].has_ended():
send("You can no longer vote.")
else:
poll_list["channel_or_poll_name"].add_vote(persons_vote)
#send the tally
send("%d people have now voted!" % poll_list["channel_or_poll_name"].tally_votes())
Of course, you'd have to edit the poll class to fit your needs, i.e. to allow multiple values in a vote, to record who is voting what (if you want that), etc.
As for checking if the poll has ended, you could edit the poll class to have the stop time, and have a function that returns True/False whether that time has passed or not. Possibly look at the docs for the datetime module...?
Anyway, hope this helps.

Equivalent to GOTO in conditions, Python

Since there is no goto operator in Python, what technique can be used instead?
Condition
If it is true, go to thread 1, if is false, go to thread 2
In thread we do something small and after that we go to thread 2 where all other actions take place.
Since there is no goto operator in Python, what technique can be used instead?
Constructing your code logically and semantically.
if condition:
perform_some_action()
perform_other_actions()
def thread_1():
# Do thread_1 type stuff here.
def thread_2():
# Do thread_2 type stuff here.
if condition:
thread_1()
# If condition was false, just run thread_2().
# If it was true then thread_1() will return to this point.
thread_2()
edit: I'm assuming that by "thread" you mean a piece of code (otherwise known as a subroutine or a function). If you're talking about threads as in parallel execution then you'll need more detail in the question.
To the best of my knowledge it's not present (thankfully), but you should check this link
The "goto" module was an April Fool's joke, published on 1st April
2004. Yes, it works, but it's a joke nevertheless. Please don't use it in real code!
Python is designed to support good coding practices and GOTO is not one of them. It may lead to unreadable program logic, if not used properly.
I suggest to learn code your program in a Python way, do not stick with (sometimes bad) habits from other programming languages. See Python documentation, real mature Python programs and learn.
def thread1():
#write your thread 1 code here
print("entered no is 1")
def thread2():
#write your thread 2 code here
print("Number is greater or less then one.")
def main():
a=input()
if a==1:
thread1()
elif a<=1 or a>=1:
thread2()
#you can use recursion here in case if you want to use agin and again
#if you want to print serveral time you can use looping.
for i in range(4):
main()
#if you want to run goto forever and ever and ever then remove loop in
#this code.
#this code will enable you the equivalent of goto statement.
This is what I use every time in Python 3.x.

Categories

Resources