How do I do the receive function to print "waiting" while the function send does not send the args?
Well, I really don't know how I can do it, I thought about join() method, but I tried this:
import threading
import random
waiting = True
def receive(a=""):
while waiting:
print "[receive] waiting for args"
print "[receive] Args received: %s" % a # args received from send function
def send(args):
global waiting
if waiting:
if random.randint(1,3) == 2:
waiting = False
print "[send] Args sent"
receive(a=args) # send the args
fargs = ["hello, world", "foo", "bar", "foobar", 12]
t1 = threading.Thread(target=receive, args=[])
t2 = threading.Thread(target=send, args=[fargs])
t1.start()
t2.start()
Sometimes this works, but sometimes I get in a infinite loop.
#EDIT
Now it works fine:
import threading
import random
waiting = True
def receive(a=""):
while waiting:
print "[receive] waiting for args"
if a:
print "[receive] Args received: %s" % a
def send(args):
global waiting
while waiting:
if random.randint(1,3) == 2:
waiting = False
print "[send] Args sent"
receive(a=args)
fargs = ["hello, world", "foo", "bar", "foobar", 12]
t1 = threading.Thread(target=receive, args=[])
t2 = threading.Thread(target=send, args=[fargs])
t1.start()
t2.start()
Is there a better way to do it?
Sorry for my english.
I know the thread is quite old, but expanding on the self answer by OP i created a class that prints a string while a given function is running.
import threading
import queue
import time
import getpass
class DotsPrinter:
def __init__(self, float_dots_frequency=1,
string_to_print_while_waiting="."):
self.float_dots_frequency = float_dots_frequency
self.string_to_print_while_waiting = string_to_print_while_waiting
self.bool_waiting = True
self.output_queue = queue.Queue()
def print_dots(self):
if self.bool_waiting:
print("Waiting ", end="", flush=True)
while self.bool_waiting:
print(self.string_to_print_while_waiting, end="",
flush=True)
time.sleep(self.float_dots_frequency)
def function_wrapper(self, function, *args, **kwargs):
self.output_queue.put(function(*args, **kwargs))
self.bool_waiting = False
def print_dots_while_executing(self, function, *args, **kwargs):
t1 = threading.Thread(target=self.print_dots)
t2 = threading.Thread(target=self.function_wrapper, args=
[function, *args], kwargs={**kwargs})
t1.start()
t2.start()
return self.output_queue.get()
the usage is quite simple:
def count_till_timeout(timeout):
start_time = time.time()
n = 0
while time.time() - start_time < timeout:
n += 1
return n
n = DotsPrinter().print_dots_while_executing(count_till_timeout, 5)
print(n)
I didn't test it exstensively so it might have some bugs, and i am not an expert with threading, therefore I don't know if a thing like this should be done, but I hope it helps someone. I'm using it to print dots while pandas downloads data from a sql DB.
Related
Hi I am trying to make it so 2 threads will change the other one but I can't figure it out this is an example of what I have
Import time
Import threading
s=0
def thing1():
time.sleep(1)
s+=1
def thing2():
print(s)
t = threading.Thread(target = thing1)
t.start()
t2 = threading.Thread(target = thing2)
t2.start()
When they run thing2 will print 0, not the seconds. I have it so they run later this is just all the code that's necessary
You need to use a semaphore so that each thread is not accessing the variable at the same time. However, any two threads can access the same variable s using global.
import threading
import time
s = 0
sem = threading.Semaphore()
def thing1():
global s
for _ in range(3):
time.sleep(1)
sem.acquire()
s += 1
sem.release()
def thing2():
global s
for _ in range(3):
time.sleep(1)
sem.acquire()
print(s)
sem.release()
t = threading.Thread(target = thing1)
t.start()
t2 = threading.Thread(target = thing2)
t2.start()
I Have 2 Code That Preferred To Have Faster Processing
First Code
( On My Recent Thread Someone Pointed Out That My Threading Code Is Wrong )
He Stated That No Matter The Value Of TotalThread It Won't Process Faster
class ThreadingPower(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue= queue
def run(self):
while True:
Manager = self.queue.get()
for Numbers,HWID in Manager:
r = requests.post(URL, data=payload) # License Checker Required Numbers ( Buyer Code ) And HWID ( License Code )
data = (r.text)
if ('Verified' in data):
with open(resultsFile,'a+') as results:
results.write("The Number : "+str(Numbers)+" Is Verified By The "+str(HWID))
results.close()
print str(HWID)+" Is Server Verified"
else:
print str(HWID)+" Is Not Server Verified"
self.queue.task_done()
if __name__ == "__main__":
for i in range(TotalThread):
t = ThreadingPower(queue)
t.setDaemon(False)
t.start()
queue.put(credentials)
queue.join()
The Credentials Are Tupples
[
['UniqueHWID', 'BuyerCode'],
['UniqueHWID', 'BuyerCode'],
['UniqueHWID', 'BuyerCode']
]
The Second Code
class ThreadingPower(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue= queue
def run(self):
while True:
Performance = self.queue.get()
for Name,ScoreA,ScoreB,ScoreC in Performance:
TScore = (ScoreA+ScoreB+ScoreC)/3
print Name+" Has Scored :"+TScore
if (TScore >= PassScore):
print Name+" Has Passed"
# Sending Message To The Server With Name Has Pass
else:
print Name+" Has Failed"
# Sending Message To The Server With Name Has Failed
if __name__ == "__main__":
for i in range(TotalThread):
t = ThreadingPower(queue)
t.setDaemon(False)
t.start()
queue.put(TestSheet)
queue.join()
With TestSheet Looking Like This
[
['StudentName', 'Test1', 'Test2', 'Test3'],
['StudentName', 'Test1', 'Test2', 'Test3'],
['StudentName', 'Test1', 'Test2', 'Test3']
]
I'm Still Learning A Few About Python,Sorry For Asking So Much Question
I Haven't Test The Second Code But Since The Threading Part Is Base From The First Code I Think It Has The Same Issue
Go one Step back, try first without threading.
def run(p):
Performance = p
Name, ScoreA, ScoreB, ScoreC = Performance
TScore = int((ScoreA + ScoreB + ScoreC) / 3)
print('{} Has Scored:{}'.format(Name, TScore))
if TScore >= PassScore:
print(Name + " Has Passed")
else:
print(Name + " Has Failed")
if __name__ == "__main__":
PassScore = 10
# Name ScoreA, ScoreB, ScoreC
TestSheet = [['StudentName1', 1, 2, 3],
['StudentName2', 4, 5, 6],
['StudentName3', 7, 8, 9]]
for p in TestSheet:
run(p)
If the result met your needs, add threading.
class ThreadingPower(threading.Thread):
...
def run(self):
Performance = self.queue.get()
...
if __name__ == "__main__":
...
for p in TestSheet:
queue.put(p)
...
Question: He Stated That No Matter The Value Of TotalThread It Won't Process Faster
What you are doing is,
Starting n Threads
All Threads waiting at queue.get()
Put ONE Message into the Queue
Only ONE Thread can get this Message and have to do ALL the jobs.
Change your code to put the 3 jobs from your TestSheet one after the other.
for job in TestSheet:
queue.put(job)
This is invalid Python, you have to change this to your new queue Data:
for in Name,ScoreA,ScoreB,ScoreC in Performance:
Second, you puting a List of str into the queue and want to do some math, this will FAIL also!
Below there is some fully functioning code.
I am planning to execute this code through command line, however I would like it to end after 60 seconds.
Does anyone know the best way of going about this?
Thanks in advance.
import time
class listener(StreamListener):
def on_data(self, data):
try:
print data
saveFile = open('twitDB.csv','a')
saveFile.write(data)
saveFile.write('\n')
saveFile.close()
return True
except BaseException, e:
print 'failed ondata,' ,str(e)
time.sleep(5)
def on_error(self, status):
print status
Try this out:
import os
import time
from datetime import datetime
from threading import Timer
def exitfunc():
print "Exit Time", datetime.now()
os._exit(0)
Timer(5, exitfunc).start() # exit in 5 seconds
while True: # infinite loop, replace it with your code that you want to interrupt
print "Current Time", datetime.now()
time.sleep(1)
There are some more examples in this StackOverflow question: Executing periodic actions in Python
I think the use of os._exit(0) is discouraged, but I'm not sure. Something about this doesn't feel kosher. It works, though.
You could move your code into a daemon thread and exit the main thread after 60 seconds:
#!/usr/bin/env python
import time
import threading
def listen():
print("put your code here")
t = threading.Thread(target=listen)
t.daemon = True
t.start()
time.sleep(60)
# main thread exits here. Daemon threads do not survive.
Use signal.ALARM to get notified after a specified time.
import signal, os
def handler(signum, frame):
print '60 seconds passed, exiting'
cleanup_and_exit_your_code()
# Set the signal handler and a 60-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(60)
run_your_code()
From your example it is not obvious what the code will exactly do, how it will run and what kind of loop it will iterate. But you can easily implement the ALARM signal to get notified after the timeout has expired.
This is my favorite way of doing timeout.
def timeout(func, args=None, kwargs=None, TIMEOUT=10, default=None, err=.05):
if args is None:
args = []
elif hasattr(args, "__iter__") and not isinstance(args, basestring):
args = args
else:
args = [args]
kwargs = {} if kwargs is None else kwargs
import threading
class InterruptableThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.result = None
def run(self):
try:
self.result = func(*args, **kwargs)
except:
self.result = default
it = InterruptableThread()
it.start()
it.join(TIMEOUT* (1 + err))
if it.isAlive():
return default
else:
return it.result
I hope this is an easy way to execute a function periodically and end after 60 seconds:
import time
import os
i = 0
def executeSomething():
global i
print(i)
i += 1
time.sleep(1)
if i == 10:
print('End')
os._exit(0)
while True:
executeSomething()
I'm currently learning Python and Classes and I have a basic question, but I didn't find any answer to it. Let's say I have this dummy class
class DomainOperations:
def __init__(self, domain):
self.domain = domain
self.domain_ip = ''
self.website_thumbnail = ''
def resolve_domain(self):
#resolve domain to ipv4 and save to self.domain_ip
def generate_website_thumbnail(self):
#generate website thumbnail and save the url to self.website_thumbnail
I want to run simultaneously resolve_domain and generate_website_thumbnail and when the threads are finished I want to print the IP and the thumbnail.
EDIT: I know I should use threads, maybe something like this
r = DomainOperations('google.com')
t1 = threading.Thread(target=r.resolve_domain)
t1.start()
t2 = threading.Thread(target=r.generate_website_thumbnail)
t2.start()
But should I use them outside the Class? Should I write another Class to handle Threads?
What is the right way to do that?
If you call them from the class, it is as simple as:
import threading
class DomainOperations:
def __init__(self):
self.domain_ip = ''
self.website_thumbnail = ''
def resolve_domain(self):
self.domain_ip = 'foo'
def generate_website_thumbnail(self):
self.website_thumbnail= 'bar'
def run(self):
t1 = threading.Thread(target=self.resolve_domain)
t2 = threading.Thread(target=self.generate_website_thumbnail)
t1.start()
t2.start()
t1.join()
t2.join()
print(self.domain_ip, self.website_thumbnail)
if __name__ == '__main__':
d = DomainOperations()
d.run()
You can inherit Thread class in DomainOperation, in this way code would be more clean and easily understandable. you have to override a run() method.
from threading import Thread
class DomainOperations(Thread):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.domain_ip = ''
self.website_thumbnail = ''
def resolve_domain(self):
self.domain_ip = 'foo'
def generate_website_thumbnail(self):
self.website_thumbnail= 'bar'
def run(self):
#domain will be resolved on first thread
self.resolve_domain()
#thumbnail will be resolved on second OR newly created below thread
thread2 = Thread(target=self.generate_website_thumbnail)
thread.start()
# thread1 will wait for thread2
self.join()
# thread2 will wait for thread1, if it's late.
thread2.join()
# here it will print ip and thumbnail before exiting first thread
print(self.domain_ip, self.website_thumbnail)
And you will start your threads in this way.
if __name__ == '__main__':
thread1 = DomainOperations()
thread1.start()
def post_test(tbid, line_num, response_time):
"""
:param tbid: 参数id
:return:
"""
# 请求参数
data = {'tbId': tbid, 'conditions': [{"key": "", "type": 1}], 'pageNum': 1, 'pageSize': 12}
# 请求启动时间
start = time.time()
# post请求
r = requests.post(url=url, data=json.dumps(data), headers=headers)
# 请求结束时间
end = time.time()
# 保留两位小数
finall_time = float('%.2f' % float(end - start))
text = json.loads(r.text)
# IO写入 只写入200的
with open('text6.csv', 'a', newline='') as csvfile:
if text['statusCode'] == '200':
throughput = line_num * response_time / finall_time
throughput = float('%.2f' % float(throughput))
print('the perf_counter time of %s is %s and the content is %s ,throughput is %s' % (
tbid, finall_time, json.loads(r.text), throughput))
spamwriter = csv.writer(csvfile, dialect='excel')
spamwriter.writerow([tbid] + [finall_time] + [throughput])
def start_thread(csv_name):
tbid, response_time_sort, throughput_sort = read_csv(csv_name)
print(tbid)
line_num = len(tbid)
response_times = 5
for j in range(response_times):
for i in tbid:
t = threading.Thread(target=post_test, args=(i, line_num, response_times))
t.start()
t.join()
I don't know how to call a method in a class, especially if it has initialization parameters, but you can try this method。 I'm trying to use multiple processes to solve this problem, right。
The following code executes two threads (multithread), each with different time delays so that each thread will finish at a different time.
Once both threads are finished module display1.py issues a print statement saying they are BOTH finished.
I would like module display1.py to issue a 'finished' statement for EACH thread AS EACH thread finishes
How can i do this ... amendments to my working code appreciated! I'd like to change as little of the current code as possible so a better form of variable transfer between the two modules might be what I'm after
display1.py
from threads1 import *
manager = ThreadManager()
manager.start(False)
print (manager.GetResults())
threads1.py
from threading import Thread
import time
class ThreadManager:
def __init__(self):
pass
def start(self, answer):
self.answer = answer
thread_refs = []
t1 = MyThread(70, 'Not finished')
t1.daemon = True
t1.start()
t2 = MyThread(2, 'Not finished')
t2.daemon = True
t2.start()
while True:
if t1.AskFinished == 'Finished' and t2.AskFinished == 'Finished': #If I break the loop after EACH site, Only the first to finish will be sent via GetResults to display1.py
global results
results = [t1.AskFinished, t2.AskFinished]
print("Both Finished")
break
def GetResults(self):
global results
return(results)
class MyThread(Thread):
def __init__(self, SleepWait, AskFinished):
Thread.__init__(self)
self.SleepWait = SleepWait
self.AskFinished = AskFinished
def run(self):
time.sleep(self.SleepWait)
self.AskFinished = 'Finished'
What you have here (entering a very tight check loop in the main thread) is a very naive approach to threading in many languages, but especially in python where GIL contention will just slow the threads down a great bit.
What is a better idea is instead using queue.Queue to push info when a thread is completed. This allows the main thread to block on the queue instead, which is less CPU intensive as well as allowing you to know (out of order) which one is finished.
The changes you would need to make:
at the top of the module threads1.py:
import queue
finished_queue = queue.Queue()
in your start():
num_finished = 0
while True:
info = finished_queue.get()
num_finished += 1
if info is t1:
print("t1 finished")
else:
print("t2 finished")
if num_finished == 2:
global results
results = [t1.AskFinished, t2.AskFinished]
print("Both Finished")
break
and finally in run():
def run(self):
time.sleep(self.SleepWait)
self.AskFinished = 'Finished'
finished_queue.put(self)
Some more fundamental modifications I'd make is actually pushing the result into the queue and then fetching the results out, skipping the extra step before GetResults. Furthermore, if GetResults had to stay, I'd pass them through a field on self e.g. self.results = [t1.AskFinished, t2.AskFinished]
Update:
Ok, so you want to know more about how to have display1.py print the results. It would be helpful if you could explain why it matters, because that might make a difference in how you should do this, but here's a first approach:
# threads1.py
from threading import Thread
import time
class ThreadManager:
def __init__(self):
self.threads = {}
def start(self):
t1 = MyThread(4)
t1.daemon = True
t1.start()
self.threads[1] = t1
t2 = MyThread(1)
t2.daemon = True
t2.start()
self.threads[2] = t2
def is_alive(self, thread_id):
return self.threads[thread_id].is_alive()
def GetResults(self): # or you could just access results directly
return self.results
class MyThread(Thread):
def __init__(self, SleepWait):
Thread.__init__(self)
self.SleepWait = SleepWait
def run(self):
time.sleep(self.SleepWait)
And then...
# display1.py
from threads1 import *
manager = ThreadManager()
manager.start()
t1_state = t2_state = True
while manager.is_alive(1) or manager.is_alive(2):
time.sleep(1)
if manager.is_alive(1) != t1_state:
print("t1 finished")
t1_state = manager.is_alive(1)
if manager.is_alive(2) != t2_state:
print("t2 finished")
t2_state = manager.is_alive(2)
if not manager.is_alive(1) and not manager.is_alive(2):
print("Both Finished")
break
You should eventually consider using a Queue as suggested by Crast; but let's focus on getting this right first.
Original Post:
There are a number of problems with this code.
First, you should use t1.is_alive() to check if a thread is finished. There's no need to reimplement it with AskFinished.
Second, the while True: loop in threads1.py is doing nothing at a furious rate while it waits for your threads to terminate. Take a look at the cpu usage while this is running if you don't believe me. You should throw a time.sleep(1) statement in there.
Third, why are you using a global var to return your results? That's a really strange thing to do. Just store it in self!
And finally, why does display1.py have to print the messages? Why can't thread1.py do that?
With these four points in mind, here's a thread1.py that works more sensibly:
from threading import Thread
import time
class ThreadManager:
def __init__(self):
self.results = None
def start(self, answer): # why is "answer" here?
self.answer = answer
thread_refs = []
t1 = MyThread(4, 'Not finished')
t1.daemon = True
t1.start()
t2 = MyThread(1, 'Not finished')
t2.daemon = True
t2.start()
t1_state = t2_state = True
while t1.is_alive() or t2.is_alive():
time.sleep(1)
if t1.is_alive() != t1_state:
print("t1 finished")
t1_state = t1.is_alive()
if t2.is_alive() != t2_state:
print("t2 finished")
t2_state = t2.is_alive()
if not t1.is_alive() and not t2.is_alive():
self.results = [t1.AskFinished, t2.AskFinished]
print("Both Finished")
break
def GetResults(self): # or you could just access results directly
return self.results
class MyThread(Thread):
def __init__(self, SleepWait, AskFinished):
Thread.__init__(self)
self.SleepWait = SleepWait
self.AskFinished = AskFinished
def run(self):
time.sleep(self.SleepWait)
self.AskFinished = 'Finished'
Now, this still doesn't do exactly what you wanted, because you asked for display.py to do the displaying. To make that work, you'd have to put your while True loop in display.py and add an ThreadManager.is_alive() method that display.py could use to check whether a thread is alive or not. If you want to see how to do that let me know.
Im not familiar with threading but since no answers yet ill give it a shot.
In this:
Cant you just add two if statements before hand?
while True:
if t1.askFinished == 'Finished':
print("t1 Finished")
if t2.askFinished == 'Finished':
print("t2 Finished")
if t1.AskFinished == 'Finished' and t2.AskFinished == 'Finished': #If I break the loop after EACH site, Only the first to finish will be sent via GetResults to display1.py
global results
results = [t1.AskFinished, t2.AskFinished]
print("Both Finished")
break
edit: I tried changing your code as little as possible... it's not very well written though tbh. (No offense)