Welcome, guest | Sign In | My Account | Store | Cart

When you're new at threading, using threads can be a bit daunting at first. If all you want is just to "run this function in parallel (= asynchronously) to the main program code", then this recipe can be of use. Simply use "@run_async" as a decorator for the function you want to run asynchronously. A call to that function will return immediately but the function itself will run in parallel.

Python, 57 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/env python

def run_async(func):
	"""
		run_async(func)
			function decorator, intended to make "func" run in a separate
			thread (asynchronously).
			Returns the created Thread object

			E.g.:
			@run_async
			def task1():
				do_something

			@run_async
			def task2():
				do_something_too

			t1 = task1()
			t2 = task2()
			...
			t1.join()
			t2.join()
	"""
	from threading import Thread
	from functools import wraps

	@wraps(func)
	def async_func(*args, **kwargs):
		func_hl = Thread(target = func, args = args, kwargs = kwargs)
		func_hl.start()
		return func_hl

	return async_func

if __name__ == '__main__':
	from time import sleep

	@run_async
	def print_somedata():
		print 'starting print_somedata'
		sleep(2)
		print 'print_somedata: 2 sec passed'
		sleep(2)
		print 'print_somedata: 2 sec passed'
		sleep(2)
		print 'finished print_somedata'

	def main():
		print_somedata()
		print 'back in main'
		print_somedata()
		print 'back in main'
		print_somedata()
		print 'back in main'

	main()

If you run the snippet, you will see:

starting print_somedata
back in main
starting print_somedata
back in main
starting print_somedata
back in main

<2s of no activity>

print_somedata: 2 sec passed
print_somedata: 2 sec passed
print_somedata: 2 sec passed

<2s of no activity>

print_somedata: 2 sec passed
print_somedata: 2 sec passed
print_somedata: 2 sec passed

<2s of no activity>

finished print_somedata
finished print_somedata
finished print_somedata

2 comments

Sandy Norton 15 years ago  # | flag

Nice use of decorators for async threaded funcs... can you do something similar with the multiprocessing module?

Tetsuya Morimoto 13 years, 6 months ago  # | flag

I tried using multiprocessing module. By replacing threading module with multiprocessing, it also works well. The diff is below. It's nice recipe!

@@ -22,12 +22,12 @@
             t1.join()
             t2.join()
     """
-    from threading import Thread
+    from multiprocessing import Process
     from functools import wraps

     @wraps(func)
     def async_func(*args, **kwargs):
-        func_hl = Thread(target = func, args = args, kwargs = kwargs)
+        func_hl = Process(target = func, args = args, kwargs = kwargs)
         func_hl.start()
         return func_hl