from threading import Thread, Lock, current_thread
from queue import Queue
import time
def worker(q, Lock):
while True:
value = q.get()
#processing...
print(f'in {current_thread().name} got {value}')
q.task_done()
if __name__ == "__main__":
q = Queue()
num_threads = 10
for i in range(num_threads):
thread = Thread(target=worker)
thread.daemon=True
thread.start()
for i in range(1, 21):
q.put(i)
q.join()
print('end main')
I keep getting an error in Python 3.9, anyone have a solution, its not taking in "import time" and "Lock"
I want to know how to stop a running function outside of it. Here is how it should be:
def smth():
time.sleep(5) # Just an example
smth.stop()
Thanks for your help
Here's an example using the multiprocessing library:
from multiprocessing import Process
import time
def foo():
print('Starting...')
time.sleep(5)
print('Done')
p = Process(target=foo) #make process
p.start() #start function
time.sleep(2) #wait 2 secs
p.terminate() #kill it
print('Killed')
Output:
Starting...
Killed
Basically, what this code does is:
Create a process p which runs the function foo when started
Wait 2 seconds to simulate doing other stuff
End the process p with p.terminate()
Since p never passes time.sleep(5) in foo, it doesn't print 'Done'
Run this code online
Figured it out, i think? Runs as expected. I'm not able to view the original code so I wrote this new one up. Is there a better way to do this?
import time
import threading
def threadee():
f = open(r'log.txt')
for line in f:
print(line)
time.sleep(0.2)
def threader():
while True:
threadee()
def main():
thread = threading.Thread(target=threader)
thread.start()
while True:
print('main thread running')
print(threading.enumerate())
time.sleep(1)
if __name__ == '__main__':
main()
I'm trying to use process in order to define a time for a function.
I sucessfully created a simple process and run it:
from multiprocessing import Process
import time
stemp = list()
#simple function for testing purpose
def f(name):
print('hello, ', name)
stemp.append(name)
#define a process and run it
p = Process(target=f, args=('bob',))
p.run()
But when I try to use p.join to define a timeout (see code bellow). I get the error message "AttributeError: 'Process' object has no attribute '_target'"
if __name__ == '__main__':
# We create a Process
p = Process(target=f, args=('bob',))
# We start the process and we block for 5 seconds.
p.start()
p.join(timeout=5)
p.run()
# We terminate the process.
p.terminate()
Any idea, what I'm doing wrong?
I am using Python 3.7 on Windows.
What I am trying to do:
- lock a method of an instance of a class, when another process has acquired that same lock.
Attempts:
I have already successfully done this, but I don't want a global variable here for the lock, but instead one completely internal to the class
from multiprocessing import Lock, freeze_support,Pool
from time import sleep
def do_work(name):
print(name+' waiting for lock to work...',end='')
sleep(2)
with lock:
print('done!')
print(name+' doing work...',end='')
sleep(5)
print('done!')
def init(olock):
global lock
lock = olock
if __name__ == '__main__':
freeze_support()
args_list = [('a'),('b'),('c')]
lock=Lock()
p=Pool(8,initializer=init,initargs=(lock,))
p.map_async(do_work,args_list)
p.close()
p.join()
When this last chunk of code runs, it takes ~17.3 seconds, because of the lock. Without the lock it takes ~7 seconds.
I have tried to implement this inside a class, but the lock does nothing, and it always runs in ~7 seconds.
class O():
def __init__(self):
self.lock=Lock()
def __getstate__(self): # used to remove multiprocess object(s) from class, so it can be pickled
self_dict=self.__dict__.copy()
del self_dict['lock']
return self_dict
def __setstate__(self,state): # used to remove multiprocess object(s) from class, so it can be pickled
self.__dict__.update(state)
def _do_work(self,name):
print(name+' waiting for lock to work...',end='')
sleep(2)
with self.lock:
print('done!')
print(name+' doing work...',end='')
sleep(5)
print('done!')
if __name__ == '__main__':
freeze_support()
c = O()
pool = Pool(8)
pool.apply_async(c._do_work,('a',))
pool.apply_async(c._do_work,('b',))
pool.apply_async(c._do_work,('c',))
pool.close()
pool.join()
Question:
So, what can I do to lock up this class instance while I call a method which interacts with a resource asynchronously through multiprocessing?
apply_async will pickle function object and send to pool worker process by queue, but as c._do_work is a bound method, the instance will be pickled too, which results in an error. you could wrap it within a plain function:
c = O()
def w(*args):
return c._do_work(*args)
if __name__ == '__main__':
pool = Pool(1)
pool.apply_async(w, ('a',))
...
and you should remove __setstate__/__getstate__.