Multitask to update the file contept every second with python - python

Im trying to write a chat logic, so here what I want to do
def chatlogic():
talk=True
while talk:
if __name__ == '__main__':
Thread(target = fluse).start()
message = raw_input('enter a message: ')
if not message: #Ending Conversation if empty message was sent
talk=False
conv_file.write('[%s]%s: %s\n' %(msgtime,user,message))
#conv_file.flush()
return 'Conversation Ended'
def fluse():
while True:
time.sleep(1)
conv_file.fluse()
the file must update every second, nomatter what you are doing.
What am i doing wrong?
note: I have never used multitasking before

There are many problems in this code, but the one you seem to be asking about is here:
while talk:
if __name__ == '__main__':
Thread(target = fluse).start()
This means that each time through the loop—that is, once per message—you're going to fire off a new fluse thread. And that thread loops forever, calling conv_file.fluse() every second until the end of time.
So, if you type messages at 0.3, 2.7, and 5.1 seconds after app startup, you're going to get a fluse at 5.3 seconds, another at 5.7, another at 6.1, and so on.
If you want this to only happen once/second, just start a single thread, instead of starting a new one each time through the loop. For example:
if __name__ == '__main__':
Thread(target = fluse).start()
while talk:
# etc.
If, instead, you want it to happen a second after each write, but not every second again after that, just take the loop out of the function:
def fluse():
time.sleep(1)
conv_file.fluse()
Although in this case, threading.Timer is an easier way to do the same thing.
Anyway, even with this fix, as I said, there are a number of other problems:
You're calling a file method that doesn't exist—presumably you meant flush instead of fluse?
The file doesn't exist either. Maybe you meant it to be a global, created outside the functions? Or an argument to them?
You're trying to loop forever until an empty message, but you call return each time through the loop, which means you're only going to loop once.
There's no way to exit your program, because you fire off a non-daemon background thread that runs forever.
You never call the chatlogic function anyway, so the program just exits immediately without doing any work.
If I fix all of the other errors in your program, and add something that shows me whether the fluse thread is doing its job, it does something… and maybe you can tell us whether it's the thing you wanted.
from threading import Thread
import time
def chatlogic(conv_file):
user = 'Nobody'
t = Thread(target=flusher, args=[conv_file])
t.daemon=True
t.start()
while True:
message = raw_input('enter a message: ')
if not message: #Ending Conversation if empty message was sent
break
msgtime = time.asctime()
conv_file.write('[%s]%s: %s\n' %(msgtime,user,message))
return 'Conversation Ended'
def flusher(conv_file):
while True:
time.sleep(1)
print 'Flushing the file now'
conv_file.flush()
if __name__ == '__main__':
conv_file = open('convfile.txt', 'w')
chatlogic(conv_file)
This is still a strange design. The file is being flushed once/second even if you didn't write anything, and that there's no guarantee it actually gets flushed at the end, and so on. But this is what it sounds like you were attempting to do.

Related

Is there any way for console programs to change their execution way, due to some event, like e.g. key press or some event in code?

All programs which I see in tutorials are console and code is executed from first line to the last line and if there is while everything starts from the first line. Is there any way for console programs to change their execution way, due to some event, like e.g. key press or some event in code? The best example of what I want to do is router CLI. Where can I find such examples?
def main():
while(True):
initial_setup() #choose IPs to monitor
while(True):
do_some_work() # do monitor the IPs
I need some listener in the secons while which detects keypresses and then I go to initial setup, meanwhile do_some_work works and only after I finish adittional changes in initial_setup do_some_work restarts.
Sorry I am noob and not very good in explaining probaly because English is not native for me. The best example from real life I can name is CLI of router, you can setup intreface and meanwhile router do routing in the background.
Code for Sergio S:
import threading
import time
def hello():
while(True):
print("Hello")
time.sleep(2)
def hi():
while(True):
print("hi")
time.sleep(2)
def press_key():
a=input()
a=False
return a
def circle():
MrBoolean=True
while(MrBoolean):
thr=[]
thr.append(threading.Thread(target=hello))
thr.append(threading.Thread(target=hi))
thr.append(threading.Thread(target=press_key))
for i in thr:
i.start()
for i in thr:
i.join()
mrBoolean=thr[3]
def main():
while(True):
circle()
main()
From your description, it seems you're searching for something called multithreading: while one part of the application does one thing, the other does something else. See these other questions for more details: How to use threading in Python? , How to stop a looping thread in Python?
whats_typed = input('Say Aah:')
if whats_typed.strip() == 'Aah':
print('Thanks!')
else:
print('Whoops. Your input was:', whats_typed)
The above changes what is executed depending on user input when the program is run.

Using thread in while loop causes problems with LED blink

I've been hung up on a problem for a couple of days, now. I've spent hours searching message boards and have come up empty.
I have a program that pulls data from an API, parses it with JSON, and displays it on an LCD screen. I want an LED light to blink when data meets a certain condition. I have been fairly successful so far. The issue I am running into is when a thread is called to start the blink from my main while loop, and the main while loop restarts, it appears that the thread is then called again. This causes my LEDs to start acting wacky after each subsequent while loop restart. Any suggestions?
I tried using v.isAlive() == False" in hopes that the thread wouldn't restart but that wasn't helpful. I just want the thread to start once if the condition is met and then continue blinking the LED until the condition is not met. Since I use an LCD screen, the data is on a continuous loop.
Here is a very simplified snippet of my program:
def partCloudBlink():
while True:
allLEDon()
time.sleep(2.5)
yellowLEDon()
time.sleep(1)
allLEDoff()
def partCloudBlink_start():
v = threading.Thread(target=partCloudBlink)
if v.isAlive() == False:
v.daemon = True
v.start()
RUNNING = True
try:
while RUNNING:
if weather in ("Partly Cloudy"):
partCloudBlink_start()
print "Current conditions: %s" % (conditions) #unrelated to the question, just program filler
except KeyboardInterrupt:
RUNNING = False
Thank you very much!
It's because a new thread object is created every time partCloudBlink_start is called. v.isAlive() is always False since it's a new thread.
You can create a global variable or something similar to store the thread object depending on your code structure.

Python module function returning immediately in thread

I've written a couple of twitter scrapers in python, and am writing another script to keep them running even if they suffer a timeout, disconnection, etc.
My current solution is as follows:
Each scraper file has a doScrape/1 function in it, which will start up a scraper and run it once, eg:
def doScrape(logger):
try:
with DBWriter(logger=logger) as db:
logger.log_info("starting", __name__)
s = PastScraper(db.getKeywords(), TwitterAuth(), db, logger)
s.run()
finally:
logger.log_info("Done", __name__)
Where run is a near-infinite loop, which won't break unless there is an exception.
In order to run one of each kind of scraper at once, I'm using this code (with a few extra imports):
from threading import Thread
class ScraperThread(Thread):
def __init__(self, module, logger):
super(ScraperThread, self).__init__()
self.module = module # Module should contain a doScrape(logger) function
self.logger = logger
def run(self):
while True:
try:
print "Starting!"
print self.module.doScrape
self.module.doScrape(self.logger)
except: # if for any reason we get disconnected, reconnect
self.logger.log_debug("Restarting scraper", __name__)
if __name__ == "__main__":
with Logger(level="all", handle=open(sys.argv[1], "a")) as l:
past = ScraperThread(PastScraper, l)
stream = ScraperThread(StreamScraper, l)
past.start()
stream.start()
past.join()
stream.join()
However, it appears that my call of doScrape from above is returning immediately, hence "Starting!" is printed in the console repeatedly, and that "Done" message in the finally block is not written to the log, whereas when run individually like so:
if __name__ == "__main__":
# Example instantiation
from Scrapers.Logging import Logger
with Logger(level="all", handle=open(sys.argv[1], "a")) as l:
doScrape(l)
The code runs forever, as expected. I'm a bit stumped.
Is there anything silly that I might have missed?
get rid of the diaper pattern in your run() method, as in: get rid of that catch-all exception handler. You'll probably get the error printed there then. I think there may be something wrong in the DBWriter or other code you're calling from your doScrape function. Perhaps it is not thread-safe. That would explain why running it from the main program directly works, but calling it from a thread fails.
Aha, solved it! It was actually that I didn't realise that a default argument (here in TwitterAuth()) is evaluated at definition time. TwitterAuth reads the API key settings from a file handle, and the default argument opens up the default config file. Since this file handle is generated at definition time, both threads had the same handle, and once one had read it, the other one tried to read from the end of the file, throwing an exception. This is remedied by resetting the file before use, and using a mutex.
Cheers to Irmen de Jong for pointing me in the right direction.

Python not querying database in loop

I currently have a process running that should call a method every 10 seconds. I see that it actually calls the method at that interval, but it seems to not execute something in the code. Weird thing is, is that when I cancel the loop, and start it new it does actually do it the first time. Then when I keep it running it does not do anything.
def main():
try:
while True:
read()
time.sleep(10)
except KeyboardInterrupt:
pass
Above is the loop, and the code here is actually the beginning of the method that is being called, and I found out that it does not actually get results in the results, while the file has changed. In this case it gets data from a .json file
def read():
message = Query()
results = DB.search(message.pushed == False)
Am I overlooking something?
Solved. I had the DB declared globally and that did not go so well. It is being fixed by declaring it just before the statement.

How to have input while a while loop ( or similar) is executed

I do believe that thread may accomplish this, although I am not sure. Most of the threads out there that address this problem doesn't address it to match my problem. I have created a simple mud-like fighting system that executes when you 'fight' an NPC. I have the code that runs under a while loop that checks health between you and NPC and if one of you dies then the loop ends.
However
During the loop I want to have it where a user can type in commands, instead of being stuck watching a looping code block without you being able to do anything. From what I have read online it looks like thread module may be of some help to me? Also if anyone has PyGame experience, maybe looking into that would be a solution? Please let me know what you think.
Below is a very simple example of what I am trying to accomplish.
import time
fighting = True
while fighting:
# do the magic here
time.sleep(4) # to give it a nice even pace between loop intervals
Although at any time i want to be able do input a command like a skill or spell.
Any ideas or suggestions?
You can separate your human interface and fight game into separate threads. The fight game uses a queue for input, which uses a timeout to continue. Here is a very simple queue structure that should minimally do what you want.
import time
import threading
import Queue
def fighter(input_queue):
while True:
start = time.time()
# do stuff
wait = time.time() - start()
if wait <= 0.0:
wait = 0
try:
msg = input_queue.get(wait, wait)
if msg == 'done':
return
# do something else with message
except Queue.Empty:
pass
def main():
input_queue = Queue.Queue()
fight_thread = threading.Thread(target=fighter, args=(input_queue,))
fight_thread.start()
while True:
msg = raw_input('hello ') # py 2.x
input_queue.put(msg)
if msg == 'done':
break
fight_thread.join()
If you only want this to work on Windows, and you want to keep your simple event loop:
fighting = True
inputbuf = ''
while fighting:
# do the magic here
while msvcrt.khbit():
newkey = msvcrt.getwche()
inputbuf += newkey
if newkey == '\r':
process_command(inputbuf)
inputbuf = ''
time.sleep(4) # to give it a nice even pace between loop intervals
On the other hand, if you want to use a background thread, it would be a lot simpler:
def background():
for line in sys.stdin:
process_command(line)
bt = threading.Thread(target=background)
bt.start
fighting = True
while fighting:
# do the magic here
time.sleep(4) # to give it a nice even pace between loop intervals
This works cross-platform, and it gives normal line-buffered input (including full readline support), which people will probably like.
However, I'm assuming you want that process_command to share information with the # do the magic here code, and possibly even to set fighting = False. If you do that without any thread synchronization, it will no longer work cross-platform. (It may work on both Windows CPython and Unix CPython, but will probably not work on IronPython or Jython—or, worse, it will work most of the time but randomly fail just often enough that you have to fix it but not often enough that you can debug it…)
What you may be looking for is a non-blocking raw_input implementation. This would allow the loop to keep going while allowing the user a possibility at entering commands.
There is an example of an implementation of this here and here. Maybe you can adapt one of them to suit your purpose.
Edit:
Or, if you're working on Windows...

Categories