Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 1 | # |
| 2 | # A test file for the `multiprocessing` package |
| 3 | # |
Benjamin Peterson | 4469d0c | 2008-11-30 22:46:23 +0000 | [diff] [blame] | 4 | # Copyright (c) 2006-2008, R Oudkerk |
| 5 | # All rights reserved. |
| 6 | # |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 7 | |
Raymond Hettinger | 40fc59d | 2011-04-26 13:55:55 -0700 | [diff] [blame] | 8 | import time |
| 9 | import sys |
| 10 | import random |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 11 | from queue import Empty |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 12 | |
| 13 | import multiprocessing # may get overwritten |
| 14 | |
| 15 | |
| 16 | #### TEST_VALUE |
| 17 | |
| 18 | def value_func(running, mutex): |
| 19 | random.seed() |
| 20 | time.sleep(random.random()*4) |
| 21 | |
| 22 | mutex.acquire() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 23 | print('\n\t\t\t' + str(multiprocessing.current_process()) + ' has finished') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 24 | running.value -= 1 |
| 25 | mutex.release() |
| 26 | |
| 27 | def test_value(): |
| 28 | TASKS = 10 |
| 29 | running = multiprocessing.Value('i', TASKS) |
| 30 | mutex = multiprocessing.Lock() |
| 31 | |
| 32 | for i in range(TASKS): |
| 33 | p = multiprocessing.Process(target=value_func, args=(running, mutex)) |
| 34 | p.start() |
| 35 | |
| 36 | while running.value > 0: |
| 37 | time.sleep(0.08) |
| 38 | mutex.acquire() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 39 | print(running.value, end=' ') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 40 | sys.stdout.flush() |
| 41 | mutex.release() |
| 42 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 43 | print() |
| 44 | print('No more running processes') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 45 | |
| 46 | |
| 47 | #### TEST_QUEUE |
| 48 | |
| 49 | def queue_func(queue): |
| 50 | for i in range(30): |
| 51 | time.sleep(0.5 * random.random()) |
| 52 | queue.put(i*i) |
| 53 | queue.put('STOP') |
| 54 | |
| 55 | def test_queue(): |
| 56 | q = multiprocessing.Queue() |
| 57 | |
| 58 | p = multiprocessing.Process(target=queue_func, args=(q,)) |
| 59 | p.start() |
| 60 | |
| 61 | o = None |
| 62 | while o != 'STOP': |
| 63 | try: |
| 64 | o = q.get(timeout=0.3) |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 65 | print(o, end=' ') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 66 | sys.stdout.flush() |
| 67 | except Empty: |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 68 | print('TIMEOUT') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 69 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 70 | print() |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 71 | |
| 72 | |
| 73 | #### TEST_CONDITION |
| 74 | |
| 75 | def condition_func(cond): |
| 76 | cond.acquire() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 77 | print('\t' + str(cond)) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 78 | time.sleep(2) |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 79 | print('\tchild is notifying') |
| 80 | print('\t' + str(cond)) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 81 | cond.notify() |
| 82 | cond.release() |
| 83 | |
| 84 | def test_condition(): |
| 85 | cond = multiprocessing.Condition() |
| 86 | |
| 87 | p = multiprocessing.Process(target=condition_func, args=(cond,)) |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 88 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 89 | |
| 90 | cond.acquire() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 91 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 92 | cond.acquire() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 93 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 94 | |
| 95 | p.start() |
| 96 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 97 | print('main is waiting') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 98 | cond.wait() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 99 | print('main has woken up') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 100 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 101 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 102 | cond.release() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 103 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 104 | cond.release() |
| 105 | |
| 106 | p.join() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 107 | print(cond) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 108 | |
| 109 | |
| 110 | #### TEST_SEMAPHORE |
| 111 | |
| 112 | def semaphore_func(sema, mutex, running): |
| 113 | sema.acquire() |
| 114 | |
| 115 | mutex.acquire() |
| 116 | running.value += 1 |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 117 | print(running.value, 'tasks are running') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 118 | mutex.release() |
| 119 | |
| 120 | random.seed() |
| 121 | time.sleep(random.random()*2) |
| 122 | |
| 123 | mutex.acquire() |
| 124 | running.value -= 1 |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 125 | print('%s has finished' % multiprocessing.current_process()) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 126 | mutex.release() |
| 127 | |
| 128 | sema.release() |
| 129 | |
| 130 | def test_semaphore(): |
| 131 | sema = multiprocessing.Semaphore(3) |
| 132 | mutex = multiprocessing.RLock() |
| 133 | running = multiprocessing.Value('i', 0) |
| 134 | |
| 135 | processes = [ |
| 136 | multiprocessing.Process(target=semaphore_func, |
| 137 | args=(sema, mutex, running)) |
| 138 | for i in range(10) |
| 139 | ] |
| 140 | |
| 141 | for p in processes: |
| 142 | p.start() |
| 143 | |
| 144 | for p in processes: |
| 145 | p.join() |
| 146 | |
| 147 | |
| 148 | #### TEST_JOIN_TIMEOUT |
| 149 | |
| 150 | def join_timeout_func(): |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 151 | print('\tchild sleeping') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 152 | time.sleep(5.5) |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 153 | print('\n\tchild terminating') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 154 | |
| 155 | def test_join_timeout(): |
| 156 | p = multiprocessing.Process(target=join_timeout_func) |
| 157 | p.start() |
| 158 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 159 | print('waiting for process to finish') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 160 | |
| 161 | while 1: |
| 162 | p.join(timeout=1) |
| 163 | if not p.is_alive(): |
| 164 | break |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 165 | print('.', end=' ') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 166 | sys.stdout.flush() |
| 167 | |
| 168 | |
| 169 | #### TEST_EVENT |
| 170 | |
| 171 | def event_func(event): |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 172 | print('\t%r is waiting' % multiprocessing.current_process()) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 173 | event.wait() |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 174 | print('\t%r has woken up' % multiprocessing.current_process()) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 175 | |
| 176 | def test_event(): |
| 177 | event = multiprocessing.Event() |
| 178 | |
| 179 | processes = [multiprocessing.Process(target=event_func, args=(event,)) |
| 180 | for i in range(5)] |
| 181 | |
| 182 | for p in processes: |
| 183 | p.start() |
| 184 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 185 | print('main is sleeping') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 186 | time.sleep(2) |
| 187 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 188 | print('main is setting event') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 189 | event.set() |
| 190 | |
| 191 | for p in processes: |
| 192 | p.join() |
| 193 | |
| 194 | |
| 195 | #### TEST_SHAREDVALUES |
| 196 | |
| 197 | def sharedvalues_func(values, arrays, shared_values, shared_arrays): |
| 198 | for i in range(len(values)): |
| 199 | v = values[i][1] |
| 200 | sv = shared_values[i].value |
| 201 | assert v == sv |
| 202 | |
| 203 | for i in range(len(values)): |
| 204 | a = arrays[i][1] |
| 205 | sa = list(shared_arrays[i][:]) |
| 206 | assert a == sa |
| 207 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 208 | print('Tests passed') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 209 | |
| 210 | def test_sharedvalues(): |
| 211 | values = [ |
| 212 | ('i', 10), |
| 213 | ('h', -2), |
| 214 | ('d', 1.25) |
| 215 | ] |
| 216 | arrays = [ |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 217 | ('i', list(range(100))), |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 218 | ('d', [0.25 * i for i in range(100)]), |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 219 | ('H', list(range(1000))) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 220 | ] |
| 221 | |
| 222 | shared_values = [multiprocessing.Value(id, v) for id, v in values] |
| 223 | shared_arrays = [multiprocessing.Array(id, a) for id, a in arrays] |
| 224 | |
| 225 | p = multiprocessing.Process( |
| 226 | target=sharedvalues_func, |
| 227 | args=(values, arrays, shared_values, shared_arrays) |
| 228 | ) |
| 229 | p.start() |
| 230 | p.join() |
| 231 | |
Benjamin Peterson | 58ea9fe | 2008-08-19 19:17:39 +0000 | [diff] [blame] | 232 | assert p.exitcode == 0 |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 233 | |
| 234 | |
| 235 | #### |
| 236 | |
| 237 | def test(namespace=multiprocessing): |
| 238 | global multiprocessing |
| 239 | |
| 240 | multiprocessing = namespace |
| 241 | |
Raymond Hettinger | 40fc59d | 2011-04-26 13:55:55 -0700 | [diff] [blame] | 242 | for func in [test_value, test_queue, test_condition, |
| 243 | test_semaphore, test_join_timeout, test_event, |
| 244 | test_sharedvalues]: |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 245 | |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 246 | print('\n\t######## %s\n' % func.__name__) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 247 | func() |
| 248 | |
| 249 | ignore = multiprocessing.active_children() # cleanup any old processes |
| 250 | if hasattr(multiprocessing, '_debug_info'): |
| 251 | info = multiprocessing._debug_info() |
| 252 | if info: |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 253 | print(info) |
| 254 | raise ValueError('there should be no positive refcounts left') |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 255 | |
| 256 | |
| 257 | if __name__ == '__main__': |
| 258 | multiprocessing.freeze_support() |
| 259 | |
| 260 | assert len(sys.argv) in (1, 2) |
| 261 | |
| 262 | if len(sys.argv) == 1 or sys.argv[1] == 'processes': |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 263 | print(' Using processes '.center(79, '-')) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 264 | namespace = multiprocessing |
| 265 | elif sys.argv[1] == 'manager': |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 266 | print(' Using processes and a manager '.center(79, '-')) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 267 | namespace = multiprocessing.Manager() |
| 268 | namespace.Process = multiprocessing.Process |
| 269 | namespace.current_process = multiprocessing.current_process |
| 270 | namespace.active_children = multiprocessing.active_children |
| 271 | elif sys.argv[1] == 'threads': |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 272 | print(' Using threads '.center(79, '-')) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 273 | import multiprocessing.dummy as namespace |
| 274 | else: |
Christian Heimes | aae1b70 | 2008-11-28 11:23:26 +0000 | [diff] [blame] | 275 | print('Usage:\n\t%s [processes | manager | threads]' % sys.argv[0]) |
| 276 | raise SystemExit(2) |
Benjamin Peterson | e711caf | 2008-06-11 16:44:04 +0000 | [diff] [blame] | 277 | |
| 278 | test(namespace) |