diff --git a/README.Rmd b/README.Rmd index dcd3c7c..7ef9a5e 100644 --- a/README.Rmd +++ b/README.Rmd @@ -29,7 +29,23 @@ import ezpq # `ezpq`: an easy parallel queueing system. -Read this on [GitHub](https://github.com/dm3ll3n/ezpq) or [my site](https://www.donaldmellenbruch.com/project/ezpq/). +> Read this on [GitHub](https://github.com/dm3ll3n/ezpq) or [my site](https://www.donaldmellenbruch.com/project/ezpq/). + +## How to get it + +Install from [PyPI](https://pypi.org/project/ezpq/) with: + +```python +pip install ezpq +``` + +Optional packages: + +```python +pip install pandas # required for plots +pip install plotnine # required for plots +pip install tqdm # required for progress bars +``` ## Overview @@ -59,22 +75,6 @@ The queueing system uses `multiprocessing.Process` by default and can also run j * Built-in logging to CSV. * Customizable visualizations of queue operations. -## How to get it - -Install from [PyPI](https://pypi.org/project/ezpq/) with: - -```python -pip install ezpq -``` - -Optional packages: - -```python -pip install pandas # required for plots -pip install plotnine # required for plots -pip install tqdm # required for progress bars -``` - ## Quickstart Suppose you wanted to speed up the following code, which runs 60 operations that take anywhere from 0s to 2s. With an average job time of ~1s, this operation should take ~60s. @@ -311,6 +311,44 @@ with ezpq.Queue(6) as Q: ![](docs/imgs/tqdm_map.gif) +### starmap + +`starmap` is similar to `map`, but operates on a list of lists, with each nested list being unpacked as arguments to the function. + +```{python, echo=TRUE} +def my_pow(x, k): + return '{}^{} = {}'.format(x, k, x**k) + +# list of lists to iterate over. +args_list = [[x, x%4] # (x, k) + for x in range(100)] + +# starmap +with ezpq.Queue(10) as Q: + output = Q.starmap(my_pow, iterable=args_list) + +[x['output'] for x in output[:10]] +``` + +### startmapkw + +Same as `starmap`, but operations on a list of *dicts* to be expanded as kwargs to the function. + +```{python, echo=TRUE} +def my_pow(x, k): + return '{}^{} = {}'.format(x, k, x**k) + +# list of dicts to iterate over. +kwargs_list = [{ 'x':x, 'k':x%4 } # (x, k) + for x in range(100)] + +# starmapkw +with ezpq.Queue(10) as Q: + output = Q.starmapkw(my_pow, iterable=kwargs_list) + +[x['output'] for x in output[:10]] +``` + ### dispose The queueing operations performed by `ezpq.Queue` are performed on a periodic basis. By default, the `poll` parameter for a Queue is `0.1` seconds. This "pulse" thread will continue firing until the Queue is disposed of. @@ -336,7 +374,7 @@ In the above graphic, notice how same-colored bars never overlap. These bars rep ### Lane Error Handling -You may want to short-circuit a synchronous lane if a job in the lane fails. You can do this by specifying `skip_on_lane_error=True` when putting a job in the queue. If specified and the preceding job has a non-zero exit code, this job will not be run. +You may want to short-circuit a synchronous lane if a job in the lane fails. You can do this by specifying `stop_on_lane_error=True` when putting a job in the queue. If specified and the preceding job has a non-zero exit code, this job will not be run. ```{python, echo=TRUE} def reciprocal(x): diff --git a/README.md b/README.md index 620c409..52fe341 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,42 @@ # `ezpq`: an easy parallel queueing system. -* [`ezpq`: an easy parallel queueing system.](#ezpq-an-easy-parallel-queueing-system) - * [Overview](#overview) - * [Features](#features) - * [How to get it](#how-to-get-it) - * [Quickstart](#quickstart) - * [ezpq.Queue](#ezpqqueue) - * [ezpq.Job](#ezpqjob) - * [put](#put) - * [size](#size) - * [wait](#wait) - * [get](#get) - * [collect](#collect) - * [map](#map) - * [dispose](#dispose) - * [Synchronous Lanes](#synchronous-lanes) - * [Lane Error Handling](#lane-error-handling) - * [ezpq.Plot](#ezpqplot) - * [More Examples](#more-examples) - -Read this on [GitHub](https://github.com/dm3ll3n/ezpq) or [my -site](https://www.donaldmellenbruch.com/project/ezpq/). +> Read this on [GitHub](https://github.com/dm3ll3n/ezpq) or [my site](https://www.donaldmellenbruch.com/project/ezpq/). + +- [How to get it](#how-to-get-it) +- [Overview](#overview) +- [Features](#features) +- [Quickstart](#quickstart) +- [ezpq.Queue](#ezpq.queue) +- [ezpq.Job](#ezpq.job) + - [put](#put) + - [size](#size) + - [wait](#wait) + - [get](#get) + - [collect](#collect) + - [map](#map) + - [starmap](#starmap) + - [startmapkw](#startmapkw) + - [dispose](#dispose) +- [Synchronous Lanes](#synchronous-lanes) + - [Lane Error Handling](#lane-error-handling) +- [ezpq.Plot](#ezpq.plot) +- [More Examples](#more-examples) + +## How to get it + +Install from [PyPI](https://pypi.org/project/ezpq/) with: + +``` python +pip install ezpq +``` + +Optional packages: + +``` python +pip install pandas # required for plots +pip install plotnine # required for plots +pip install tqdm # required for progress bars +``` ## Overview @@ -53,22 +69,6 @@ also run jobs with `threading.Thread`. - Built-in logging to CSV. - Customizable visualizations of queue operations. -## How to get it - -Install from [PyPI](https://pypi.org/project/ezpq/) with: - -``` python -pip install ezpq -``` - -Optional packages: - -``` python -pip install pandas # required for plots -pip install plotnine # required for plots -pip install tqdm # required for progress bars -``` - ## Quickstart Suppose you wanted to speed up the following code, which runs 60 @@ -143,7 +143,7 @@ print( output[0] ) ## {'args': [0], ## 'callback': None, ## 'cancelled': False, - ## 'ended': datetime.datetime(2019, 2, 18, 20, 21, 0, 902915), + ## 'ended': datetime.datetime(2019, 3, 13, 0, 48, 52, 811248), ## 'exception': None, ## 'exitcode': 0, ## 'function': 'random_sleep', @@ -153,11 +153,11 @@ print( output[0] ) ## 'name': 1, ## 'output': 1.3444218515250481, ## 'priority': 100, - ## 'processed': datetime.datetime(2019, 2, 18, 20, 21, 0, 955396), - ## 'qid': 'f4717edb', - ## 'runtime': 1.3515939712524414, - ## 'started': datetime.datetime(2019, 2, 18, 20, 20, 59, 551321), - ## 'submitted': datetime.datetime(2019, 2, 18, 20, 20, 59, 446199), + ## 'processed': datetime.datetime(2019, 3, 13, 0, 48, 52, 867387), + ## 'qid': '13318d36', + ## 'runtime': 1.3500409126281738, + ## 'started': datetime.datetime(2019, 3, 13, 0, 48, 51, 461207), + ## 'submitted': datetime.datetime(2019, 3, 13, 0, 48, 51, 357405), ## 'timeout': 0} Easily convert output to a `pandas` dataframe: @@ -169,11 +169,11 @@ print( df.head()[['id', 'output', 'runtime', 'exitcode']] ) ``` ## id output runtime exitcode - ## 0 1 1.344422 1.351594 0 - ## 1 2 0.634364 0.640723 0 - ## 2 3 1.456034 1.461620 0 - ## 3 4 0.737965 0.743645 0 - ## 4 5 0.736048 0.742260 0 + ## 0 1 1.344422 1.350041 0 + ## 1 2 0.634364 0.638938 0 + ## 2 3 1.456034 1.459830 0 + ## 3 4 0.737965 0.741742 0 + ## 4 5 0.736048 0.739848 0 Use `ezpq.Plot` to generate a Gannt chart of the job timings. @@ -335,9 +335,9 @@ with ezpq.Queue(6) as Q: ## 'Total: 60; Waiting: 31; Working: 6; Completed: 23' ## 'Total: 60; Waiting: 24; Working: 6; Completed: 30' ## 'Total: 60; Waiting: 17; Working: 6; Completed: 37' - ## 'Total: 60; Waiting: 12; Working: 6; Completed: 42' + ## 'Total: 60; Waiting: 11; Working: 6; Completed: 43' ## 'Total: 60; Waiting: 6; Working: 6; Completed: 48' - ## 'Total: 60; Waiting: 1; Working: 6; Completed: 53' + ## 'Total: 60; Waiting: 0; Working: 5; Completed: 55' ## 'Total: 60; Waiting: 0; Working: 1; Completed: 59' ## 'Total: 60; Waiting: 0; Working: 0; Completed: 60' @@ -407,6 +407,42 @@ call. Include `show_progress=True` to get output `tqdm` progress bar. ![](docs/imgs/tqdm_map.gif) +### starmap + +`starmap` is similar to `map`, but operates on a list of lists, with +each nested list being unpacked as arguments to the function. + +``` python +def my_pow(x, k): + return '{}^{} = {}'.format(x, k, x**k) +# list of lists to iterate over. +args_list = [[x, x%4] # (x, k) + for x in range(100)] +# starmap +with ezpq.Queue(10) as Q: + output = Q.starmap(my_pow, iterable=args_list) + +[x['output'] for x in output[:10]] +``` + +### startmapkw + +Same as `starmap`, but operations on a list of *dicts* to be expanded as +kwargs to the function. + +``` python +def my_pow(x, k): + return '{}^{} = {}'.format(x, k, x**k) +# list of dicts to iterate over. +kwargs_list = [{ 'x':x, 'k':x%4 } # (x, k) + for x in range(100)] +# starmapkw +with ezpq.Queue(10) as Q: + output = Q.starmapkw(my_pow, iterable=kwargs_list) + +[x['output'] for x in output[:10]] +``` + ### dispose The queueing operations performed by `ezpq.Queue` are performed on a @@ -435,7 +471,7 @@ synchronously. ### Lane Error Handling You may want to short-circuit a synchronous lane if a job in the lane -fails. You can do this by specifying `skip_on_lane_error=True` when +fails. You can do this by specifying `stop_on_lane_error=True` when putting a job in the queue. If specified and the preceding job has a non-zero exit code, this job will not be run. diff --git a/README.rst b/README.rst index b80439e..ed8fed5 100644 --- a/README.rst +++ b/README.rst @@ -1,14 +1,15 @@ ``ezpq``: an easy parallel queueing system. =========================================== -- ```ezpq``: an easy parallel queueing - system. <#ezpq-an-easy-parallel-queueing-system>`__ + Read this on `GitHub `__ or `my + site `__. + +- `How to get it <#how-to-get-it>`__ - `Overview <#overview>`__ - `Features <#features>`__ -- `How to get it <#how-to-get-it>`__ - `Quickstart <#quickstart>`__ -- `ezpq.Queue <#ezpqqueue>`__ -- `ezpq.Job <#ezpqjob>`__ +- `ezpq.Queue <#ezpq.queue>`__ +- `ezpq.Job <#ezpq.job>`__ - `put <#put>`__ - `size <#size>`__ @@ -16,17 +17,33 @@ - `get <#get>`__ - `collect <#collect>`__ - `map <#map>`__ + - `starmap <#starmap>`__ + - `startmapkw <#startmapkw>`__ - `dispose <#dispose>`__ - `Synchronous Lanes <#synchronous-lanes>`__ - `Lane Error Handling <#lane-error-handling>`__ -- `ezpq.Plot <#ezpqplot>`__ +- `ezpq.Plot <#ezpq.plot>`__ - `More Examples <#more-examples>`__ -Read this on `GitHub `__ or `my -site `__. +How to get it +------------- + +Install from `PyPI `__ with: + +.. code:: python + + pip install ezpq + +Optional packages: + +.. code:: python + + pip install pandas # required for plots + pip install plotnine # required for plots + pip install tqdm # required for progress bars Overview -------- @@ -40,8 +57,7 @@ Overview The queueing system uses ``multiprocessing.Process`` by default and can also run jobs with ``threading.Thread``. -.. figure:: docs/imgs/ezpq.png - :alt: +|image0| Features -------- @@ -62,23 +78,6 @@ Features - Built-in logging to CSV. - Customizable visualizations of queue operations. -How to get it -------------- - -Install from `PyPI `__ with: - -.. code:: python - - pip install ezpq - -Optional packages: - -.. code:: python - - pip install pandas # required for plots - pip install plotnine # required for plots - pip install tqdm # required for progress bars - Quickstart ---------- @@ -88,24 +87,24 @@ operations that take anywhere from 0s to 2s. With an average job time of .. code:: python - import time - import random - def random_sleep(x): - random.seed(x) - n = random.uniform(0.5, 1.5) - time.sleep(n) - return n + import time + import random + def random_sleep(x): + random.seed(x) + n = random.uniform(0.5, 1.5) + time.sleep(n) + return n .. code:: python - start = time.time() - output = [random_sleep(x) for x in range(60)] - end = time.time() - print('> Runtime: ' + str(end - start)) + start = time.time() + output = [random_sleep(x) for x in range(60)] + end = time.time() + print('> Runtime: ' + str(end - start)) :: - ## '> Runtime: 58.932034969329834' + ## '> Runtime: 58.932034969329834' Here is the function ran in parallel with an ``ezpq`` Queue of 6 workers. Thus, the runtime of the above operation will be reduced from @@ -113,26 +112,26 @@ workers. Thus, the runtime of the above operation will be reduced from .. code:: python - import time - import random - import ezpq - start = time.time() - with ezpq.Queue(6) as Q: - output = Q.map(random_sleep, range(60)) - end = time.time() - print('> Runtime: ' + str(end - start)) + import time + import random + import ezpq + start = time.time() + with ezpq.Queue(6) as Q: + output = Q.map(random_sleep, range(60)) + end = time.time() + print('> Runtime: ' + str(end - start)) Here is the same scenario, using the ``@ezpq.Queue`` decorator. .. code:: python - @ezpq.Queue(6) - def random_sleep(x): - random.seed(x) - n = random.uniform(0.5, 1.5) - time.sleep(n) - return n - output = random_sleep(iterable=range(60)) + @ezpq.Queue(6) + def random_sleep(x): + random.seed(x) + n = random.uniform(0.5, 1.5) + time.sleep(n) + return n + output = random_sleep(iterable=range(60)) While ``map()`` and the decorator are useful for quick-n-simple parallization, the essential functions of an ``ezpq`` Queue include @@ -140,67 +139,66 @@ parallization, the essential functions of an ``ezpq`` Queue include .. code:: python - with ezpq.Queue(6) as Q: - for x in range(60): - Q.put(random_sleep, args=x) - Q.wait() - output = Q.collect() + with ezpq.Queue(6) as Q: + for x in range(60): + Q.put(random_sleep, args=x) + Q.wait() + output = Q.collect() The output is a list of dicts containing verbose information about each job, along with its output, and exit code. .. code:: python - print( output[0] ) + print( output[0] ) :: - ## {'args': [0], - ## 'callback': None, - ## 'cancelled': False, - ## 'ended': datetime.datetime(2019, 2, 18, 20, 21, 0, 902915), - ## 'exception': None, - ## 'exitcode': 0, - ## 'function': 'random_sleep', - ## 'id': 1, - ## 'kwargs': None, - ## 'lane': None, - ## 'name': 1, - ## 'output': 1.3444218515250481, - ## 'priority': 100, - ## 'processed': datetime.datetime(2019, 2, 18, 20, 21, 0, 955396), - ## 'qid': 'f4717edb', - ## 'runtime': 1.3515939712524414, - ## 'started': datetime.datetime(2019, 2, 18, 20, 20, 59, 551321), - ## 'submitted': datetime.datetime(2019, 2, 18, 20, 20, 59, 446199), - ## 'timeout': 0} + ## {'args': [0], + ## 'callback': None, + ## 'cancelled': False, + ## 'ended': datetime.datetime(2019, 3, 13, 0, 48, 52, 811248), + ## 'exception': None, + ## 'exitcode': 0, + ## 'function': 'random_sleep', + ## 'id': 1, + ## 'kwargs': None, + ## 'lane': None, + ## 'name': 1, + ## 'output': 1.3444218515250481, + ## 'priority': 100, + ## 'processed': datetime.datetime(2019, 3, 13, 0, 48, 52, 867387), + ## 'qid': '13318d36', + ## 'runtime': 1.3500409126281738, + ## 'started': datetime.datetime(2019, 3, 13, 0, 48, 51, 461207), + ## 'submitted': datetime.datetime(2019, 3, 13, 0, 48, 51, 357405), + ## 'timeout': 0} Easily convert output to a ``pandas`` dataframe: .. code:: python - import pandas as pd - df = pd.DataFrame(output) - print( df.head()[['id', 'output', 'runtime', 'exitcode']] ) + import pandas as pd + df = pd.DataFrame(output) + print( df.head()[['id', 'output', 'runtime', 'exitcode']] ) :: - ## id output runtime exitcode - ## 0 1 1.344422 1.351594 0 - ## 1 2 0.634364 0.640723 0 - ## 2 3 1.456034 1.461620 0 - ## 3 4 0.737965 0.743645 0 - ## 4 5 0.736048 0.742260 0 + ## id output runtime exitcode + ## 0 1 1.344422 1.350041 0 + ## 1 2 0.634364 0.638938 0 + ## 2 3 1.456034 1.459830 0 + ## 3 4 0.737965 0.741742 0 + ## 4 5 0.736048 0.739848 0 Use ``ezpq.Plot`` to generate a Gannt chart of the job timings. .. code:: python - plt = ezpq.Plot(output).build(show_legend=False) - plt.save('docs/imgs/quickstart.png') + plt = ezpq.Plot(output).build(show_legend=False) + plt.save('docs/imgs/quickstart.png') -.. figure:: docs/imgs/quickstart.png - :alt: +|image1| ezpq.Queue ---------- @@ -217,44 +215,44 @@ The ``Queue`` class implements the queueing system, which is itself a :: - ## Help on function __init__ in module ezpq.Queue: - ## - ## __init__(self, n_workers=8, max_size=0, job_runner=, auto_remove=False, auto_start=True, auto_stop=False, callback=None, log_file=None, poll=0.1, show_progress=False, qid=None) - ## Implements a parallel queueing system. - ## - ## Args: - ## n_workers: the max number of concurrent jobs. - ## - Accepts: int - ## - Default: cpu_count() - ## max_size: when > 0, will throw an exception the number of enqueued jobs exceeds this value. Otherwise, no limit. - ## - Accepts: int - ## - Default: 0 (unlimited) - ## job_runner: the class to use to invoke new jobs. - ## - Accepts: multiprocessing.Process, threading.Thread - ## - Default: multiprocessing.Process - ## auto_remove: controls whether jobs are discarded of after completion. - ## - Accepts: bool - ## - Default: False - ## auto_start: controls whether the queue system "pulse" is started upon instantiation (default), or manually. - ## - Accepts: bool - ## - Default: True - ## auto_stop: controls whether the queue system "pulse" stops itself after all jobs are complete. - ## - Accepts: bool - ## - Default: False - ## callback: optional function to execute synchronously immediately after a job completes. - ## - Accepts: function object - ## - Default: None - ## log_file: if file path is specified, job data is written to this path in CSV format. - ## - Accepts: str - ## - Default: None - ## poll: controls the pulse frequency; the amount of time slept between operations. - ## - Accepts: float - ## - Default: 0.1 - ## - ## Returns: - ## ezpq.Queue object. - ## - ## None + ## Help on function __init__ in module ezpq.Queue: + ## + ## __init__(self, n_workers=8, max_size=0, job_runner=, auto_remove=False, auto_start=True, auto_stop=False, callback=None, log_file=None, poll=0.1, show_progress=False, qid=None) + ## Implements a parallel queueing system. + ## + ## Args: + ## n_workers: the max number of concurrent jobs. + ## - Accepts: int + ## - Default: cpu_count() + ## max_size: when > 0, will throw an exception the number of enqueued jobs exceeds this value. Otherwise, no limit. + ## - Accepts: int + ## - Default: 0 (unlimited) + ## job_runner: the class to use to invoke new jobs. + ## - Accepts: multiprocessing.Process, threading.Thread + ## - Default: multiprocessing.Process + ## auto_remove: controls whether jobs are discarded of after completion. + ## - Accepts: bool + ## - Default: False + ## auto_start: controls whether the queue system "pulse" is started upon instantiation (default), or manually. + ## - Accepts: bool + ## - Default: True + ## auto_stop: controls whether the queue system "pulse" stops itself after all jobs are complete. + ## - Accepts: bool + ## - Default: False + ## callback: optional function to execute synchronously immediately after a job completes. + ## - Accepts: function object + ## - Default: None + ## log_file: if file path is specified, job data is written to this path in CSV format. + ## - Accepts: str + ## - Default: None + ## poll: controls the pulse frequency; the amount of time slept between operations. + ## - Accepts: float + ## - Default: 0.1 + ## + ## Returns: + ## ezpq.Queue object. + ## + ## None ezpq.Job -------- @@ -264,50 +262,49 @@ queue with a call to ``submit()``. :: - ## Help on function __init__ in module ezpq.Job: - ## - ## __init__(self, function, args=None, kwargs=None, name=None, priority=100, lane=None, timeout=0, suppress_errors=False, stop_on_lane_error=False) - ## Defines what to run within a `ezpq.Queue`, and how to run it. - ## - ## Args: - ## function: the function to run. - ## - Accepts: function object - ## args: optional positional arguments to pass to the function. - ## - Accepts: list, tuple - ## - Default: None - ## kwargs: optional keyword arguments to pass to the function. - ## - Accepts: dict - ## - Default: None - ## name: optional name to give to the job. Does not have to be unique. - ## - Accepts: str - ## - Default: None; assumes same name as job id. - ## priority: priority value to assign. Lower values get processed sooner. - ## - Accepts: int - ## - Default: 100 - ## lane: a sequential lane to place the job in. if it does not already exist, it will be created. - ## - Accepts: int, str; any hashable object - ## - Default: None; no lanes. - ## timeout: When > 0, if this value (in seconds) is exceeded, the job is terminated. Otherwise, no limit enforced. - ## - Accepts: float - ## - Default: 0 (unlimited) - ## - ## Returns: - ## ezpq.Job object - ## - ## None + ## Help on function __init__ in module ezpq.Job: + ## + ## __init__(self, function, args=None, kwargs=None, name=None, priority=100, lane=None, timeout=0, suppress_errors=False, stop_on_lane_error=False) + ## Defines what to run within a `ezpq.Queue`, and how to run it. + ## + ## Args: + ## function: the function to run. + ## - Accepts: function object + ## args: optional positional arguments to pass to the function. + ## - Accepts: list, tuple + ## - Default: None + ## kwargs: optional keyword arguments to pass to the function. + ## - Accepts: dict + ## - Default: None + ## name: optional name to give to the job. Does not have to be unique. + ## - Accepts: str + ## - Default: None; assumes same name as job id. + ## priority: priority value to assign. Lower values get processed sooner. + ## - Accepts: int + ## - Default: 100 + ## lane: a sequential lane to place the job in. if it does not already exist, it will be created. + ## - Accepts: int, str; any hashable object + ## - Default: None; no lanes. + ## timeout: When > 0, if this value (in seconds) is exceeded, the job is terminated. Otherwise, no limit enforced. + ## - Accepts: float + ## - Default: 0 (unlimited) + ## + ## Returns: + ## ezpq.Job object + ## + ## None .. code:: python - with ezpq.Queue(6) as Q: - for x in range(60): - priority = x % 2 # give even numbers higher priority. - job = ezpq.Job(random_sleep, args=x, priority=priority) - Q.submit(job) - Q.wait() - output = Q.collect() + with ezpq.Queue(6) as Q: + for x in range(60): + priority = x % 2 # give even numbers higher priority. + job = ezpq.Job(random_sleep, args=x, priority=priority) + Q.submit(job) + Q.wait() + output = Q.collect() -.. figure:: docs/imgs/submit.png - :alt: +|image2| put ~~~ @@ -317,11 +314,11 @@ All of its arguments are passed to ``ezpq.Job()``. .. code:: python - with ezpq.Queue(6) as Q: - for x in range(60): - Q.put(random_sleep, args=x) - Q.wait() - output = Q.collect() + with ezpq.Queue(6) as Q: + for x in range(60): + Q.put(random_sleep, args=x) + Q.wait() + output = Q.collect() size ~~~~ @@ -334,42 +331,42 @@ corresponding queue(s) will be counted. For example: .. code:: python - def print_sizes(Q): - msg = 'Total: {0}; Waiting: {1}; Working: {2}; Completed: {3}'.format( - Q.size(), - Q.size(waiting=True), - Q.size(working=True), - Q.size(completed=True) - ) - print(msg) + def print_sizes(Q): + msg = 'Total: {0}; Waiting: {1}; Working: {2}; Completed: {3}'.format( + Q.size(), + Q.size(waiting=True), + Q.size(working=True), + Q.size(completed=True) + ) + print(msg) .. code:: python - with ezpq.Queue(6) as Q: - # enqueue jobs - for x in range(60): - Q.put(random_sleep, x) - # repeatedly print sizes until complete. - while Q.size(waiting=True, working=True): - print_sizes(Q) - time.sleep(1) - print_sizes(Q) + with ezpq.Queue(6) as Q: + # enqueue jobs + for x in range(60): + Q.put(random_sleep, x) + # repeatedly print sizes until complete. + while Q.size(waiting=True, working=True): + print_sizes(Q) + time.sleep(1) + print_sizes(Q) :: - ## 'Total: 60; Waiting: 60; Working: 0; Completed: 0' - ## 'Total: 60; Waiting: 51; Working: 6; Completed: 3' - ## 'Total: 60; Waiting: 46; Working: 6; Completed: 8' - ## 'Total: 60; Waiting: 39; Working: 6; Completed: 15' - ## 'Total: 60; Waiting: 34; Working: 6; Completed: 20' - ## 'Total: 60; Waiting: 31; Working: 6; Completed: 23' - ## 'Total: 60; Waiting: 24; Working: 6; Completed: 30' - ## 'Total: 60; Waiting: 17; Working: 6; Completed: 37' - ## 'Total: 60; Waiting: 12; Working: 6; Completed: 42' - ## 'Total: 60; Waiting: 6; Working: 6; Completed: 48' - ## 'Total: 60; Waiting: 1; Working: 6; Completed: 53' - ## 'Total: 60; Waiting: 0; Working: 1; Completed: 59' - ## 'Total: 60; Waiting: 0; Working: 0; Completed: 60' + ## 'Total: 60; Waiting: 60; Working: 0; Completed: 0' + ## 'Total: 60; Waiting: 51; Working: 6; Completed: 3' + ## 'Total: 60; Waiting: 46; Working: 6; Completed: 8' + ## 'Total: 60; Waiting: 39; Working: 6; Completed: 15' + ## 'Total: 60; Waiting: 34; Working: 6; Completed: 20' + ## 'Total: 60; Waiting: 31; Working: 6; Completed: 23' + ## 'Total: 60; Waiting: 24; Working: 6; Completed: 30' + ## 'Total: 60; Waiting: 17; Working: 6; Completed: 37' + ## 'Total: 60; Waiting: 11; Working: 6; Completed: 43' + ## 'Total: 60; Waiting: 6; Working: 6; Completed: 48' + ## 'Total: 60; Waiting: 0; Working: 5; Completed: 55' + ## 'Total: 60; Waiting: 0; Working: 1; Completed: 59' + ## 'Total: 60; Waiting: 0; Working: 0; Completed: 60' wait ~~~~ @@ -384,8 +381,7 @@ completed jobs. New in v0.2.0, include ``show_progress=True`` to show a progress bar while waiting. This is equivalent to a call to ``waitpb()``. -.. figure:: docs/imgs/tqdm.gif - :alt: +|image3| get ~~~ @@ -398,16 +394,16 @@ the timeout is exceeded, ``None`` is returned. .. code:: python - with ezpq.Queue(6) as Q: - n_inputs = 60 - output = [None] * n_inputs - # enqueue jobs - for x in range(n_inputs): - Q.put(random_sleep, args=x) - - # repeatedly `get()` until queue is empty. - for i in range(n_inputs): - output[i] = Q.get(wait=True) + with ezpq.Queue(6) as Q: + n_inputs = 60 + output = [None] * n_inputs + # enqueue jobs + for x in range(n_inputs): + Q.put(random_sleep, args=x) + + # repeatedly `get()` until queue is empty. + for i in range(n_inputs): + output[i] = Q.get(wait=True) collect ~~~~~~~ @@ -419,22 +415,22 @@ before ``collect()`` if desired. .. code:: python - with ezpq.Queue(6) as Q: - # enqueue jobs - for x in range(60): - Q.put(random_sleep, x) - # wait and collect all jobs - print('Queue size before: {0}'.format(Q.size())) - Q.wait() - output = Q.collect() - print('Queue size after: {0}'.format(Q.size())) - print('Output size: {0}'.format(len(output))) + with ezpq.Queue(6) as Q: + # enqueue jobs + for x in range(60): + Q.put(random_sleep, x) + # wait and collect all jobs + print('Queue size before: {0}'.format(Q.size())) + Q.wait() + output = Q.collect() + print('Queue size after: {0}'.format(Q.size())) + print('Output size: {0}'.format(len(output))) :: - ## 'Queue size before: 60' - ## 'Queue size after: 0' - ## 'Output size: 60' + ## 'Queue size before: 60' + ## 'Queue size after: 0' + ## 'Output size: 60' map ~~~ @@ -443,8 +439,45 @@ map one call. Include ``show_progress=True`` to get output ``tqdm`` progress bar. -.. figure:: docs/imgs/tqdm_map.gif - :alt: +|image4| + +starmap +~~~~~~~ + +``starmap`` is similar to ``map``, but operates on a list of lists, with +each nested list being unpacked as arguments to the function. + +.. code:: python + + def my_pow(x, k): + return '{}^{} = {}'.format(x, k, x**k) + # list of lists to iterate over. + args_list = [[x, x%4] # (x, k) + for x in range(100)] + # starmap + with ezpq.Queue(10) as Q: + output = Q.starmap(my_pow, iterable=args_list) + + [x['output'] for x in output[:10]] + +startmapkw +~~~~~~~~~~ + +Same as ``starmap``, but operations on a list of *dicts* to be expanded +as kwargs to the function. + +.. code:: python + + def my_pow(x, k): + return '{}^{} = {}'.format(x, k, x**k) + # list of dicts to iterate over. + kwargs_list = [{ 'x':x, 'k':x%4 } # (x, k) + for x in range(100)] + # starmapkw + with ezpq.Queue(10) as Q: + output = Q.starmapkw(my_pow, iterable=kwargs_list) + + [x['output'] for x in output[:10]] dispose ~~~~~~~ @@ -467,8 +500,7 @@ to execute them in sequence. All that is required is an arbitrary lane name/id passed to the ``lane`` parameter of ``put``. Empty lanes are automatically removed. -.. figure:: docs/imgs/lanes.gif - :alt: +|image5| In the above graphic, notice how same-colored bars never overlap. These bars represent jobs that are in the same lane, which executed @@ -478,29 +510,28 @@ Lane Error Handling ~~~~~~~~~~~~~~~~~~~ You may want to short-circuit a synchronous lane if a job in the lane -fails. You can do this by specifying ``skip_on_lane_error=True`` when +fails. You can do this by specifying ``stop_on_lane_error=True`` when putting a job in the queue. If specified and the preceding job has a non-zero exit code, this job will not be run. .. code:: python - def reciprocal(x): - time.sleep(0.1) # slow things down - return 1/x # will throw DivideByZero exception + def reciprocal(x): + time.sleep(0.1) # slow things down + return 1/x # will throw DivideByZero exception .. code:: python - import random - with ezpq.Queue(6) as Q: - for i in range(100): - Q.put(reciprocal, random.randint(0, 10), lane=i%5, suppress_errors=True, stop_on_lane_error=True) - Q.wait() - output = Q.collect() - plt = ezpq.Plot(output).build(facet_by='lane', color_by='exitcode', color_pal=['red', 'blue']) - plt.save('docs/imgs/lane_error.png') + import random + with ezpq.Queue(6) as Q: + for i in range(100): + Q.put(reciprocal, random.randint(0, 10), lane=i%5, suppress_errors=True, stop_on_lane_error=True) + Q.wait() + output = Q.collect() + plt = ezpq.Plot(output).build(facet_by='lane', color_by='exitcode', color_pal=['red', 'blue']) + plt.save('docs/imgs/lane_error.png') -.. figure:: docs/imgs/lane_error.png - :alt: +|image6| ezpq.Plot --------- @@ -515,54 +546,53 @@ coloring, to faceting, :: - ## Help on function build in module ezpq.Plot: - ## - ## build(self, color_by='qid', facet_by='qid', facet_scale='fixed', show_legend=True, bar_width=1, title=None, color_pal=None, theme='bw') - ## Produces a plot based on the data and options provided to a `ezpq.Plot()` object. - ## - ## Args: - ## color_by: controls the column to use for coloring the bars. - ## - Accepts: one of 'qid', 'priority', 'lane', 'cancelled', 'exitcode', 'name', 'output' - ## - Default: 'qid' - ## facet_by: controls the column to use for facetting the plot. - ## - Accepts: one of 'qid', 'priority', 'lane', 'cancelled', 'exitcode', 'name', 'output' - ## - Default: 'qid' - ## facet_scale: controls the scale of the x/y axis across facets. - ## - Accepts: one of 'fixed', 'free', 'free_x', 'free_y' - ## - Default: 'fixed' - ## show_legend: controls whether the legend is drawn. - ## - Accepts: bool - ## - Default: True - ## bar_width: controls the bar width - ## - Accepts: float - ## - Default: 1 - ## title: optional title to be drawn above the plot. - ## - Accepts: str, None - ## - Default: None - ## theme: - ## - Accepts: 'bw', 'classic', 'gray', 'grey', 'seaborn', '538', 'dark', 'matplotlib', 'minimal', 'xkcd', 'light' - ## - Default: 'bw' - ## Returns: - ## The plot produced from plotnine.ggplot(). - ## - ## None + ## Help on function build in module ezpq.Plot: + ## + ## build(self, color_by='qid', facet_by='qid', facet_scale='fixed', show_legend=True, bar_width=1, title=None, color_pal=None, theme='bw') + ## Produces a plot based on the data and options provided to a `ezpq.Plot()` object. + ## + ## Args: + ## color_by: controls the column to use for coloring the bars. + ## - Accepts: one of 'qid', 'priority', 'lane', 'cancelled', 'exitcode', 'name', 'output' + ## - Default: 'qid' + ## facet_by: controls the column to use for facetting the plot. + ## - Accepts: one of 'qid', 'priority', 'lane', 'cancelled', 'exitcode', 'name', 'output' + ## - Default: 'qid' + ## facet_scale: controls the scale of the x/y axis across facets. + ## - Accepts: one of 'fixed', 'free', 'free_x', 'free_y' + ## - Default: 'fixed' + ## show_legend: controls whether the legend is drawn. + ## - Accepts: bool + ## - Default: True + ## bar_width: controls the bar width + ## - Accepts: float + ## - Default: 1 + ## title: optional title to be drawn above the plot. + ## - Accepts: str, None + ## - Default: None + ## theme: + ## - Accepts: 'bw', 'classic', 'gray', 'grey', 'seaborn', '538', 'dark', 'matplotlib', 'minimal', 'xkcd', 'light' + ## - Default: 'bw' + ## Returns: + ## The plot produced from plotnine.ggplot(). + ## + ## None .. code:: python - with ezpq.Queue(6) as Q: - for x in range(60): - lane = x % 5 - Q.put(random_sleep, x, timeout=1, lane=lane) - Q.wait() - output = Q.collect() + with ezpq.Queue(6) as Q: + for x in range(60): + lane = x % 5 + Q.put(random_sleep, x, timeout=1, lane=lane) + Q.wait() + output = Q.collect() .. code:: python - plt = ezpq.Plot(output).build(facet_by='lane', show_legend=False) - plt.save('docs/imgs/lanes2.png') + plt = ezpq.Plot(output).build(facet_by='lane', show_legend=False) + plt.save('docs/imgs/lanes2.png') -.. figure:: docs/imgs/lanes2.png - :alt: +|image7| Each horizontal bar represents an independent job id. The start of the gray bar indicates when the job entered the queuing system. The start of @@ -577,3 +607,13 @@ More Examples Many more examples can be found in `docs/examples.ipynb `__. + +.. |image0| image:: docs/imgs/ezpq.png +.. |image1| image:: docs/imgs/quickstart.png +.. |image2| image:: docs/imgs/submit.png +.. |image3| image:: docs/imgs/tqdm.gif +.. |image4| image:: docs/imgs/tqdm_map.gif +.. |image5| image:: docs/imgs/lanes.gif +.. |image6| image:: docs/imgs/lane_error.png +.. |image7| image:: docs/imgs/lanes2.png + diff --git a/docs/examples.ipynb b/docs/examples.ipynb index 79d1613..7cf4c33 100644 --- a/docs/examples.ipynb +++ b/docs/examples.ipynb @@ -1,2878 +1,2931 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# `ezpq` Examples" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "import os" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "if os.path.exists('../ezpq/__init__.py'):\n", - " sys.path.insert(0, '../')\n", - "import ezpq" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [], - "source": [ - "import os\n", - "import time\n", - "import random\n", - "import logging as log\n", - "import multiprocessing as mp\n", - "import threading\n", - "logger = log.getLogger()\n", - "logger.setLevel(log.INFO)\n", - "# logger.setLevel(log.DEBUG) # uncomment to view verbose output" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "from datetime import datetime" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [], - "source": [ - "# Context manager to time functions\n", - "class MyTimer():\n", - " '''https://www.blog.pythonlibrary.org/2016/05/24/python-101-an-intro-to-benchmarking-your-code/'''\n", - " def __init__(self):\n", - " self.start = time.time()\n", - "\n", - " def __enter__(self):\n", - " return self\n", - "\n", - " def __exit__(self, exc_type, exc_val, exc_tb):\n", - " end = time.time()\n", - " runtime = round(end - self.start, 3)\n", - " msg = 'Runtime: {time}'\n", - " print(msg.format(time=runtime))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Elementary example\n", - "\n", - "I'll start with a step-by-step example to illustrate the basic operations. The code below is what we want to optimize. It simply loops 10 times, sleeping 1 second each time, for a total of 10 seconds." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "source": [ - "```python\n", - "for _ in range(10):\n", - " time.sleep(1)\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create the Queue with *n* workers." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "Q = ezpq.Queue(n_workers=5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Put jobs in the Queue." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "for _ in range(10):\n", - " Q.put(time.sleep, 1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "size() will count all jobs in the waiting, working, and completed queues." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "10" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Q.size()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a list to store job data (runtime and output)." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "results = list()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`get()` is used to pop the highest priority job from the *completed* queue. The result must be stored or it will be lost.\n", - "\n", - "When no output is available and `wait` is true, the operation will wait for the next job to finish." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "done = Q.get(wait=True) # get() returns a dict\n", - "\n", - "results.append(done) # append dictionary to results list." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Count remaining jobs after the operation above." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "9" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Q.size()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`collect()` is used to repeatedly `get()` all completed jobs.\n", - "\n", - "`collect()` does not support the `wait` parameter;\n", - "\n", - "Instead, wait for all running and queued jobs to complete with `wait()` before calling `collect()`." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "Q.wait()\n", - "\n", - "done_list = Q.collect() # collect() returns a list\n", - "\n", - "results.extend(done_list) # extend result list " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Verify no jobs remain." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Q.size()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dispose of the `ezpq`. This will ensure all jobs are stopped and data is discarded." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "Q.dispose()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, inspect a single job result." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'qid': '50630fdf',\n", - " 'id': 1,\n", - " 'name': 1,\n", - " 'priority': 100,\n", - " 'lane': None,\n", - " 'timeout': 0,\n", - " 'function': 'sleep',\n", - " 'args': [1],\n", - " 'kwargs': None,\n", - " 'submitted': datetime.datetime(2019, 2, 18, 20, 20, 17, 663244),\n", - " 'started': datetime.datetime(2019, 2, 18, 20, 20, 17, 758352),\n", - " 'ended': datetime.datetime(2019, 2, 18, 20, 20, 18, 763252),\n", - " 'processed': datetime.datetime(2019, 2, 18, 20, 20, 18, 860747),\n", - " 'exitcode': 0,\n", - " 'cancelled': False,\n", - " 'runtime': 1.0048999786376953,\n", - " 'output': None,\n", - " 'exception': None,\n", - " 'callback': None}" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "results[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a pandas dataframe for a grid view of the results." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
argscallbackcancelledendedexceptionexitcodefunctionidkwargslanenameoutputpriorityprocessedqidruntimestartedsubmittedtimeout
0[1]NoneFalse2019-02-18 20:20:18.763252None0sleep1NoneNone1None1002019-02-18 20:20:18.86074750630fdf1.0049002019-02-18 20:20:17.7583522019-02-18 20:20:17.6632440
1[1]NoneFalse2019-02-18 20:20:18.767614None0sleep2NoneNone2None1002019-02-18 20:20:18.86113350630fdf1.0042432019-02-18 20:20:17.7633712019-02-18 20:20:17.6632740
2[1]NoneFalse2019-02-18 20:20:18.773731None0sleep3NoneNone3None1002019-02-18 20:20:18.86137250630fdf1.0048082019-02-18 20:20:17.7689232019-02-18 20:20:17.6633010
3[1]NoneFalse2019-02-18 20:20:18.778162None0sleep4NoneNone4None1002019-02-18 20:20:18.86159450630fdf1.0046132019-02-18 20:20:17.7735502019-02-18 20:20:17.6633300
4[1]NoneFalse2019-02-18 20:20:18.801069None0sleep5NoneNone5None1002019-02-18 20:20:18.86189450630fdf1.0061492019-02-18 20:20:17.7949202019-02-18 20:20:17.6633510
\n", - "
" - ], - "text/plain": [ - " args callback cancelled ended exception exitcode \\\n", - "0 [1] None False 2019-02-18 20:20:18.763252 None 0 \n", - "1 [1] None False 2019-02-18 20:20:18.767614 None 0 \n", - "2 [1] None False 2019-02-18 20:20:18.773731 None 0 \n", - "3 [1] None False 2019-02-18 20:20:18.778162 None 0 \n", - "4 [1] None False 2019-02-18 20:20:18.801069 None 0 \n", - "\n", - " function id kwargs lane name output priority processed \\\n", - "0 sleep 1 None None 1 None 100 2019-02-18 20:20:18.860747 \n", - "1 sleep 2 None None 2 None 100 2019-02-18 20:20:18.861133 \n", - "2 sleep 3 None None 3 None 100 2019-02-18 20:20:18.861372 \n", - "3 sleep 4 None None 4 None 100 2019-02-18 20:20:18.861594 \n", - "4 sleep 5 None None 5 None 100 2019-02-18 20:20:18.861894 \n", - "\n", - " qid runtime started submitted \\\n", - "0 50630fdf 1.004900 2019-02-18 20:20:17.758352 2019-02-18 20:20:17.663244 \n", - "1 50630fdf 1.004243 2019-02-18 20:20:17.763371 2019-02-18 20:20:17.663274 \n", - "2 50630fdf 1.004808 2019-02-18 20:20:17.768923 2019-02-18 20:20:17.663301 \n", - "3 50630fdf 1.004613 2019-02-18 20:20:17.773550 2019-02-18 20:20:17.663330 \n", - "4 50630fdf 1.006149 2019-02-18 20:20:17.794920 2019-02-18 20:20:17.663351 \n", - "\n", - " timeout \n", - "0 0 \n", - "1 0 \n", - "2 0 \n", - "3 0 \n", - "4 0 " - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = pd.DataFrame(results)\n", - "\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Lastly, visualize the steps." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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AjEAAGhzd9xxhxYvXqyXXnpJ6enpiouLU3V1tfbu3Sun06n777/f7BJhEc0OxDExMcrIyGh0Xb9+/RQVFdXqogAAAM4mPT1d69ev18cff6zi4mIdP35csbGxuuqqqzR06NBGL+0MNKbZZ5mYMWOG1q1b1+Dk0IZhaO3atfWOHAMAALQlt9utESNG6JprrtG0adN0zTXXaMSIEYThCPH5559rxIgR6tSpkxYtWtRg/SuvvKL09PTQ7cOHD2vs2LHq3Lmzbrnllnars0n/W5YvXx76OSkpSfn5+RowYIAmTpyo7t27q7S0VH/961914sQJjRo1qs2KBQAA+L6DBw/qrbfe0t69e3XixAklJycrMzNT48aNk8vlMru8djF9+nQ9/fTT8ng8oWX/+7//G5pD/fXXX+vmm2/Wu+++q+7du+vBBx/U9ddfH9q2trZWc+bM0ZYtW1RbW6sBAwZo165d6tSpk1588UXde++9OnDggNxuty677DKtWrVKvXr1kiT5fD7deeed2rp1q9xut2699VYtXbpUDodDkvTwww/roosuUn5+fpOeyxNPPKGEhARVVFSExmgPTQrEs2fPbnT5448/3mDZ7373O91zzz2tqwoAAOAsPvjgAz3yyCPq37+/DMNQYWGhRo0apZ07d2r79u164IEH6l3KuSP77W9/q4ceeqjRdT//+c81ZMgQvfjii/rXv/6liRMnavDgwRo8eLAk6bbbblN1dbV2796tbt26affu3aFw/aMf/UhvvfWWUlJSVFtbq3nz5unWW2/V3/72N0nSAw88oA8//FCfffaZamtrNX78eKWlpelXv/qVJKmoqEhTp05t8vMoKirSoEGD2jUMS02cMhEMBpv8LxAItHXNAAAAevLJJ3Xvvfdq6dKlevDBB3XfffepqqpKDz30kK644gpt2LDB7BJN9/nnn+tf//qXlixZotjYWI0ZM0aTJk3SU089JUkqLCzUtm3btGHDBqWkpMjpdGro0KGKjo6WJPXq1UspKSmh8ZxOp7744ovQ7Y0bN2r+/Pnq3r270tLSNHv2bD355JOSpMsuu0xvvfWWZs2apYSEBH3wwQc6duyYrrnmGnXp0kVDhgzRRx99FBrrhhtu0FNPPaXly5crISFB27Zta4+XSBKXbgYAABZ17NgxDR06NHR72LBhWrFihSTpv/7rv/TMM8+YVZr+/IJTnxd1kfRNGEftorXLGl/zxBNP6IknnlCfPn1011136aabbpJ08mp+ffv2VdeuXUPb/vCHP9TOnTslSe+//77S09O1aNEi/fGPf1RycrJmz56tm2++ObT97t27NWrUKFVUVMjtdmv9+vWSTr7+Bw4c0A9/+MN6Y393hcB//OMfGjNmjK6//nrddtttkqRp06YpEAho3759Ki0t1YQJE0L33bx5s1wul3r06HHao91tpUWBuLq6Wps2bdI777yjsrIyeb1ejRo1SjfeeKPi4+PDXSMAAEADffr00VtvvaVx48ZJknbu3KnevXtLOvllO7vMIb7zzjv16KOPKjExUW+//bauu+46denSRddee62qqqqUmJhYb/vExERVVlZKOjm/+NNPP9WkSZO0b98+ffLJJxo/frz69+8fugLg+eefr/Lych05ckTr1q3ToEGDJJ28WNt3431/7NraWvn9/gZfbAwEAnruueeUn5+vTp06qVOnTvr1r38d+iPGTM0+y8TXX3+tIUOG6M4771RhYaGcTqcKCwt15513aujQofr666/bok4AAIB6Zs6cqU2bNum2227Tbbfdpk2bNoXOdlVcXKwLL7zQ5Arbx/Dhw5WcnCy3262xY8fq17/+tZ577jlJCn1B7fsqKipCl3+Oi4uTy+XSggULFB0drQsuuEDXXXedduzY0eBxkpOTNX36dE2ePFl+vz90ZeLvj19RUaGYmJhGz/Jx+PBh1dXV1btgSt++fVv/AoRBs48Q//a3v5V08tuLmZmZoeWFhYX62c9+pv/3//6fnn322fBVCAAA0IgBAwZo/fr12rNnjyTp3HPPDX1S3a9fP911111mlmcap9MZOj3u4MGDVVxcrPLy8tCR3I8++ij0hbohQ4Y0a2y/36/S0lJ9++238nq96tmzpz766KPQWSe+P/apunXrpqioKJWUlOj888+XJJWUlLToOYZbswPx66+/rry8vHphWJIyMzO1aNGi0BwRAACAthYfH68RI0aYXUYD064Jqrq6sg0u3extsPzZZ5/VhAkTFB8fr3/+859avXq1Vq1aJenkHw0XXHCB5s6dq0ceeUQffPCBXnrpJf3zn/+UdPKLb/369dOSJUs0b9487d69W88//7xefPFFSdKWLVt00UUXKT09Xd98843uvvtuDR8+XF7vyTqmT5+uRYsW6cILL1Rt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laUFCxZo0KBB+uSTT7Ru3TodOXJEHo9H/fv31/Tp05WRkSFJ2rRpk/7nf/5HVVVV6tSpk376058qKyvLzKdmeU8//bS2bt1ab9nll1+uYcOGaevWrTp69Kiio6M1fPhw/epXv1JMTIxJlXYMp3u9Z82axXvBZKWlpbrlllsUFRUll8sVWj516lSlpKTwfgAsgkAMAAAAW+OzGwAAANgagRgAAAC2RiAGAACArRGIAQAAYGsEYgAAANgagRgAAAC2RiAGAACArRGIAQAAYGsEYgAtVl5eLofDoU2bNrXbY+7atUtLly5tsHzhwoVKSEhotzoAAB0HgRiApZwuEN9yyy166623TKgIAGB1brMLAIDjx48rNja2VWP07t1bvXv3DlNFAAA74QgxgCbbsGGD0tPTFRcXp3HjxumLL76ot97hcOjRRx+tt2zlypVyOByh27t27ZLD4dDLL7+sqVOnqnPnzrruuuskSX/84x81cuRIeb1ede3aVWPGjNH7778fuu/ChQuVm5ur6upqORwOORwOjRkzJrTu1CkTxcXFmjp1qrp06aL4+HhdeeWV2r17d71t0tPTdccdd2jNmjXq27evunTpoilTpujw4cOtfr0AANbAEWIATbJjxw7NnDlT06dP1/XXX6/8/PxQkG2JmTNnKjs7W9u3b5fL5ZIk7d27V7/85S91zjnnyOfzacuWLbrsssv0ySef6Ac/+IFuueUW7du3T08//bR27twpSercuXOj41dWVmrMmDFyOp1av369YmJitGTJktB4ffr0CW370ksv6fPPP9eaNWt05MgR3X333frNb36jrVu3tvj5AQCsg0AMoEkWL16sUaNGaePGjZKkK6+8UrW1tVq0aFGLxps0aZKWLVtWb9n8+fNDPweDQY0fP17vv/++Nm3apKVLl4amRTidTl100UVnHH/jxo0qLi7Wf/7zH5133nmSpNGjRystLU0rV67UY489FtrWMAy99NJLio6OlnQymC9dulTBYFBOJx+kAUBHx54ewFkFAgHl5+fr6quvrrd86tSpLR7zqquuarCsoKBAV199tVJSUuRyuRQVFaXCwkJ99tlnzR7/7bff1uDBg0NhWJK8Xq/Gjx+vd955p962o0ePDoVhSRo4cKDq6upUWlra7McFAFgPR4gBnNXhw4fl9/vVvXv3estTUlJaPOap962srNQVV1yhbt26afny5erbt69iYmJ0yy23qLa2ttnjHzt2rNH6UlJS9Omnn9ZblpiYWO+2x+ORpBY9LgDAegjEAM6qW7ducrvdDY6YfvPNN/VuR0dHy+fz1Vt27NixRsf8/hftJOm9997Tvn37tGPHDg0dOjS0vKKiokVnj/B6vSosLGyw/JtvvpHX6232eACAjospEwDOyuVyafjw4dq+fXu95c8//3y9271791ZBQUG9Za+//nqTHuP48eOS/u/orCT985//1N69e+tt5/F4dOLEibOON3LkSO3evbteKD527JjeeOMNjRw5skk1AQDsgUAMoEnuv/9+vf3225oxY4ZeffVVLV26VJs3b663zdSpU/Xcc8/p97//vV599VXdcMMN2r9/f5PGv+iii5SQkKBf//rXeu2117Rx40Zdf/316tWrV73tzjvvPPn9fj3++OP64IMPGj0KLEkzZsxQ3759ddVVV2nr1q36y1/+oiuuuEJut1uzZs1q2YsAAOiQCMQAmmTSpElav3693nzzTU2ZMkWvvfaannnmmXrbzJs3T7/4xS+Um5ur7Oxs9e3bV3fddVeTxk9JSdFzzz2n0tJSTZ48WStXrlReXp769+9fb7uJEyfq9ttv14MPPqgf//jHysnJaXS8Tp06adeuXRo6dKhmzpypadOmqWvXrvrHP/5R75RrAAA4DMMwzC4CAAAAMAtHiAEAAGBrBGIAAADYGoEYAAAAtkYgBgAAgK0RiAEAAGBrBGIAAADYGoEYAAAAtkYgBgAAgK0RiAEAAGBrBGIAAADYGoEYAAAAtkYgBgAAgK39f4JZ3WALl3jUAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ezpq.Plot(results).build()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the chart above, the colored lines overlap because the jobs were run in parallel. Contrast that with the following example using serial processing." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Practical Examples" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Shared parameters; adjust as desired." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [], - "source": [ - "n_workers = 10 # number of workers to process the queue.\n", - "n_inputs = 50 # number of inputs to the queue.\n", - "job_time = 1 # number of seconds each input will 'sleep'" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "---" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f3ad832275004ee0bb2d0388a5992673", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
argscallbackcancelledendedexceptionexitcodefunctionidkwargslanenameoutputpriorityprocessedqidruntimestartedsubmittedtimeout
0[1]NoneFalse2019-02-18 20:20:22.972163None0sleep1NoneNone1None1002019-02-18 20:20:23.0695543bd621c41.0045212019-02-18 20:20:21.9676422019-02-18 20:20:21.8624320
1[1]NoneFalse2019-02-18 20:20:22.978533None0sleep2NoneNone2None1002019-02-18 20:20:23.0699943bd621c41.0045482019-02-18 20:20:21.9739852019-02-18 20:20:21.8624700
2[1]NoneFalse2019-02-18 20:20:22.986742None0sleep3NoneNone3None1002019-02-18 20:20:23.0703163bd621c41.0053692019-02-18 20:20:21.9813732019-02-18 20:20:21.8624910
3[1]NoneFalse2019-02-18 20:20:22.994291None0sleep4NoneNone4None1002019-02-18 20:20:23.0705783bd621c41.0052362019-02-18 20:20:21.9890552019-02-18 20:20:21.8625050
4[1]NoneFalse2019-02-18 20:20:22.999577None0sleep5NoneNone5None1002019-02-18 20:20:23.0708433bd621c41.0036402019-02-18 20:20:21.9959372019-02-18 20:20:21.8625320
\n", - "
" - ], - "text/plain": [ - " args callback cancelled ended exception exitcode \\\n", - "0 [1] None False 2019-02-18 20:20:22.972163 None 0 \n", - "1 [1] None False 2019-02-18 20:20:22.978533 None 0 \n", - "2 [1] None False 2019-02-18 20:20:22.986742 None 0 \n", - "3 [1] None False 2019-02-18 20:20:22.994291 None 0 \n", - "4 [1] None False 2019-02-18 20:20:22.999577 None 0 \n", - "\n", - " function id kwargs lane name output priority processed \\\n", - "0 sleep 1 None None 1 None 100 2019-02-18 20:20:23.069554 \n", - "1 sleep 2 None None 2 None 100 2019-02-18 20:20:23.069994 \n", - "2 sleep 3 None None 3 None 100 2019-02-18 20:20:23.070316 \n", - "3 sleep 4 None None 4 None 100 2019-02-18 20:20:23.070578 \n", - "4 sleep 5 None None 5 None 100 2019-02-18 20:20:23.070843 \n", - "\n", - " qid runtime started submitted \\\n", - "0 3bd621c4 1.004521 2019-02-18 20:20:21.967642 2019-02-18 20:20:21.862432 \n", - "1 3bd621c4 1.004548 2019-02-18 20:20:21.973985 2019-02-18 20:20:21.862470 \n", - "2 3bd621c4 1.005369 2019-02-18 20:20:21.981373 2019-02-18 20:20:21.862491 \n", - "3 3bd621c4 1.005236 2019-02-18 20:20:21.989055 2019-02-18 20:20:21.862505 \n", - "4 3bd621c4 1.003640 2019-02-18 20:20:21.995937 2019-02-18 20:20:21.862532 \n", - "\n", - " timeout \n", - "0 0 \n", - "1 0 \n", - "2 0 \n", - "3 0 \n", - "4 0 " - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "with ezpq.Queue(n_workers=n_workers) as Q: # create an ezpq.Queue() with 10 workers. \n", - " for i in range(n_inputs): # create 50 jobs, each sleeping for 1 second.\n", - " Q.put(function=time.sleep, args=job_time)\n", - " \n", - " Q.waitpb() # wait for all jobs to complete.\n", - " \n", - " results = Q.collect() # collect completed jobs from queue.\n", - " \n", - "df = pd.DataFrame(results)\n", - "\n", - "df.head()" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:706: UserWarning: Saving 6.4 x 4.8 in image.\n", - " from_inches(height, units), units))\n", - "/home/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:707: UserWarning: Filename: imgs/50x1x10.png\n", - " warn('Filename: {}'.format(filename))\n" - ] - }, - { - "data": { - "image/png": "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/FMWi0UWi0UZGRnuz/17lKKjo0O5ubmaP3++oqKitHr1al26dMnjmaSkJL388suqrKxUYmKi5s+fr/Xr16uvr2/S3y8AwMzGjTGACZ06dUpFRUUqKCjQxo0b1dzc7G5ofVFUVKT8/HydOHFCoaGhkqQrV67o+eef17333qvh4WF98skneuKJJ9TS0qIHHnhAhYWF6uzs1Mcff6yzZ89KkubNmzfh/oODg8rIyFBISIiqqqpktVr19ttvu/dbunSp+9mTJ0/qp59+UmVlpa5du6adO3fqlVdeUU1Njc9/PwDAzEdjDGBCpaWlevzxx1VdXS1JWr16tZxOp/bu3evTfuvWrdO+ffs81vbs2eP+eGxsTJmZmTp//rwOHz6ssrIy97hESEiIVq1addf9q6ur1dHRoR9++EHJycmSpPT0dCUkJKiiokLvvvuu+1mXy6WTJ08qIiJC0u0GvaysTGNjYwoJ4T/SAGC24l8AAOOMjo6qublZOTk5Huu5ubk+77lmzZpxa62trcrJyZHdbldoaKjCw8PV1tamH3/80fD+DQ0Neuihh9xNsSTFxcUpMzNT3377rcez6enp7qZYkpYvX66RkRH19vYa/roAgODBjTGAcfr6+nTr1i0tWrTIY91ut/u857//7ODgoLKysrRw4UK99957SkxMlNVqVWFhoZxOp+H9BwYGJqzPbrfr8uXLHmsxMTEer+fMmSNJPn1dAEDwoDEGMM7ChQsVFhY27gb16tWrHq8jIiI0PDzssTYwMDDhnv/8hTxJampqUmdnp06dOqUVK1a413///Xef0ibi4uLU1tY2bv3q1auKi4szvB8AYPZhlALAOKGhoUpJSdGJEyc81j/99FOP1/Hx8WptbfVYO336tFdfY2hoSNLft7WS9N133+nKlSsez82ZM0d//fXXf+6XlpamS5cueTTHAwMD+vrrr5WWluZVTQCA2Y3GGMCE3njjDTU0NGjLli2qra1VWVmZjhw54vFMbm6ujh8/rg8++EC1tbXavHmzurq6vNp/1apVio6O1ksvvaS6ujpVV1dr48aNWrJkicdzycnJunXrlvbv368LFy5MeCssSVu2bFFiYqLWrFmjmpoaff7558rKylJYWJh27Njh2zcBADCr0BgDmNC6detUVVWlM2fOaP369aqrq9OxY8c8ntm9e7fy8vJUUlKi/Px8JSYmavv27V7tb7fbdfz4cfX29io7O1sVFRVyOBy67777PJ5bu3atXnzxRb3zzjt69NFHtW3btgn3mzt3rurr67VixQoVFRVp06ZNio2N1TfffOMR1QYAwJ1YXC6Xy+wiAAAAALNxYwwAAACIxhgAAACQRGMMAAAASKIxBgAAACTRGAMAAACSaIwBAAAASTTGAAAAgCQaYwAAAEASjTEAAAAgicYYAAAAkERjDAAAAEiS/gfuldx/oQWfHwAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "title='{} inputs, {}s job time, {} workers (parallel).'.format(n_inputs, job_time, n_workers)\n", - "\n", - "plt = ezpq.Plot(results).build(title=title)\n", - "\n", - "plt.save('imgs/{}x{}x{}.png'.format(n_inputs, job_time, n_workers))\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Job Priority" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Jobs are prioritized by (1) custom priority and (2) arrival time. By using a priority queue for both pending and completed jobs, you can be sure that higher priority jobs are executed and retrieved sooner.\n", - "\n", - "The default priority value is 100. Lower values take higher priority." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "6d9dfdca9a5948b996aa7ff469e7703a", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:706: UserWarning: Saving 6.4 x 4.8 in image.\n", - " from_inches(height, units), units))\n", - "/home/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:707: UserWarning: Filename: imgs/100x1x10_priority.png\n", - " warn('Filename: {}'.format(filename))\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "with ezpq.Queue(n_workers=n_workers) as Q:\n", - "\n", - " for i in range(n_inputs):\n", - " Q.put(function=time.sleep, args=job_time,\n", - " priority=int((i+1) % 10 != 0)+1) # prioritize numbers divisible by ten.\n", - "\n", - " Q.waitpb()\n", - "\n", - " results = Q.collect()\n", - "\n", - "title = '{} inputs, {}s job time, {} workers (prioritized).'.format(n_inputs, job_time, n_workers)\n", - "\n", - "plt = ezpq.Plot(results).build(title=title, color_by='priority')\n", - "\n", - "plt.save('imgs/100x1x10_priority.png')\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Threads\n", - "\n", - "By default, `ezpq.Queue` uses `multiprocessing.Process` to spawn new jobs. However, you can use `threading.Thread` instead by specifying `job_runner=Thread` when creating the Queue. Some of the differences between processes and threads are explained [here](https://medium.com/@bfortuner/python-multithreading-vs-multiprocessing-73072ce5600b).\n", - "\n", - "> Note that, inherently, `Thread` loses the ability to enforce a timeout, to kill jobs, or to obtain exit codes.\n", - "\n", - "Aside from that, there's no difference in how you interact with ezpq.\n", - "\n", - "In addition to using Threads, the example below varies the job time between 0-2 seconds." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ecb60e878f194caf8f1e9a9d1aa2dfd5", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:706: UserWarning: Saving 6.4 x 4.8 in image.\n", - " from_inches(height, units), units))\n", - "/home/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:707: UserWarning: Filename: imgs/100xNx10.png\n", - " warn('Filename: {}'.format(filename))\n" - ] - }, - { - "data": { - "image/png": "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v/6qFStW6MSJE+rRo4eefPJJ3XfffVaXBcQ9GuJ2qq6uVltbm2pqatTY2Kh58+YpLy9Pd955p9WlwQb8fr+ysrK0YMEC5eTkqLa2Vm+++aZycnJ06623Wl0ebK6mpkb9+/eXz+ezuhTY2G+//aZPP/1UL730km699VadPXtWXq/X6rKAhEBD3A5er1fbtm3T+++/r/T0dBUWFqq4uFibNm2iIYYkKS0tLexhMIMGDVJRUZFqa2s1cOBAffTRR9q5c6f8fr/69u2rl156Sfn5+RZWDLvYt2+fjh8/rtGjR+v777+XJLW2trJnEGHFihV69NFHNWjQIEkKPYGN/QJcPxridjh27JgMw1BBQUFobcCAAdq+fbuFVcHOvF6vDh48qHHjxmnz5s2qr69XdXW1MjIydPToUWVmZlpdImygra1N1dXVevHFF3Xo0KHQOnsGV/L7/Tpw4ICGDh2qp556Sl6vV3fccYfKysq0detW9gtwnfilunbwer1KT08PW8vIyFBLS4tFFcHOAoGAFi1apJtvvll33HGHkpOT1dLSoqNHj8owDPXv31+9e/e2ukzYwNq1azV48GANGDAgbJ09gyudOXNGPp9PP//8sxYsWKAlS5bozJkz+vTTT9kvQCfghLgd0tLSIprfCxcuyOPxWFQR7MowDH300UdqampSRUWFXC6XHnjgATU1NamqqkpNTU269957NXPmzIhvsuAsx48f148//qgPPvgg4j32DK6UmpoqSRo7dqyys7MlSZMnT1ZlZaXmzp3LfgGuEyfE7dCvXz9J0pEjR0Jrhw8fZj4LYQzD0NKlS3X48GGVl5eHvmFyu92aMmWKFi9erMWLF+vPP//UunXrLK4WVqutrdXp06f11FNPafr06frkk0906NAhTZ8+XRcvXmTPIExmZqays7Plcrki3uNrDHD9OCFuh7S0NA0bNkzLli3TCy+8oJMnT2rjxo167rnnrC4NNlJdXa39+/drwYIFYScze/bsUffu3ZWfn6+0tDR169ZNSUl8L+p0w4cP15AhQ0Kvt27dqp9++klvvPGGDh48yJ5BhOLiYn377be66667lJqaqrVr12ro0KF8jQE6AQ1xO82ePVtLlizRjBkz5PF49Mgjj5AwgZDGxkZ999136tatm2bOnBlaLykpUU5Ojj7++GOdOnVKqampGjJkiB5++GELq4UdpKamhn4MLl36vQS3263evXtrz5497BlEmDx5ss6ePas5c+bI7XbrrrvuUllZmXbu3Ml+Aa6TyzAMw+oiAAAAAKvwMxUAAAA4Gg0xAAAAHI2GGAAAAI5GQwwAAABHoyEGAACAo9EQAwAAwNFoiAEAAOBoNMQAAABwNBpiAO125swZuVwuffbZZzH7mFu2bFFlZWXEenl5uTIzM2NWBwAgcdEQA7C1qzXEZWVl+umnnyyoCACQaJKtLgCA87S0tMjj8VzXPfLy8pSXl9dJFQEAnIwTYgBX9cknn6iwsFDp6el66KGHdPDgwbD3XS6XFi5cGLa2aNEiuVyu0OstW7bI5XLp22+/VUlJiXr06KHJkydLkj7//HMNHz5cWVlZ6t27t0aNGqUdO3aE/m55ebkqKip0/vx5uVwuuVwujRo1KvTelSMT9fX1KikpUc+ePZWRkaExY8Zo7969YdcUFhZq7ty5qqqqUkFBgXr27KmJEyfq5MmT1/35AgDEJ06IAUS1fv16zZo1SzNmzNDUqVO1a9euUCPbEbNmzVJpaam+/PJLud1uSVJdXZ2mT5+uG2+8Ua2trVq5cqXuv/9+7dmzR7fccovKysp09OhRrVixQps3b5Yk9ejRI+r9m5ubNWrUKCUlJWnp0qVKS0vTW2+9Fbpf//79Q9d+/fXXOnDggKqqqvTXX3/phRde0LPPPqtVq1Z1+N8HAIhfNMQAolqwYIFGjBihmpoaSdKYMWPk9Xo1f/78Dt1v/Pjxeuedd8LW3njjjdCfA4GARo8erR07duizzz5TZWVlaCwiKSlJ99xzzzXvX1NTo/r6ev3+++8qKiqSJI0cOVL5+flatGiR3n333dC1hmHo66+/VmpqqqRLjXllZaUCgYCSkvjBGQA4DV/5AUTw+/3atWuXJk2aFLZeUlLS4XuOHTs2Yq22tlaTJk1STk6O3G63unXrpv379+uPP/4wff+tW7fqtttuCzXDkpSVlaXRo0frl19+Cbt25MiRoWZYkgYNGqS2tjY1Njaa/rgAgPjHCTGACCdPnpTP51Pfvn3D1nNycjp8zyv/bnNzs4qLi9WnTx+99957KigoUFpamsrKyuT1ek3f//Tp01Hry8nJ0b59+8LWevXqFfY6JSVFkjr0cQEA8Y+GGECEPn36KDk5OeLE9MSJE2GvU1NT1draGrZ2+vTpqPe8/BftJGn79u06evSo1q9fr8GDB4fW//777w6lR2RlZWn//v0R6ydOnFBWVpbp+wEAnIORCQAR3G63hgwZoi+//DJs/Ysvvgh7nZeXp9ra2rC1TZs2tetjtLS0SPrndFaSfv31V9XV1YVdl5KSoosXL/7r/YYPH669e/eGNcWnT5/WDz/8oOHDh7erJgCAM9EQA4jqtdde09atW/XEE09ow4YNqqys1LJly8KuKSkp0Zo1a/Thhx9qw4YNevzxx3Xs2LF23f+ee+5RZmam5syZo40bN6qmpkZTp05Vv379wq4rKiqSz+fTBx98oJ07d0Y9BZakJ554QgUFBRo7dqxWrVqlr776SsXFxUpOTtbzzz/fsU8CAMARaIgBRDV+/HgtXbpUP/74oyZOnKiNGzdq9erVYdfMmzdP06ZNU0VFhUpLS1VQUKDnnnuuXffPycnRmjVr1NjYqAkTJmjRokWqrq7WTTfdFHbduHHj9Mwzz+jtt9/W3XffrdmzZ0e9X/fu3bVlyxYNHjxYs2bN0mOPPabevXvr559/DotcAwDgSi7DMAyriwAAAACswgkxAAAAHI2GGAAAAI5GQwwAAABHoyEGAACAo9EQAwAAwNFoiAEAAOBoNMQAAABwNBpiAAAAOBoNMQAAAByNhhgAAACORkMMAAAAR/t/VCSXFWgc7qsAAAAASUVORK5CYII=\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from threading import Thread\n", - "\n", - "with ezpq.Queue(n_workers=n_workers, job_runner=Thread) as Q:\n", - "\n", - " for i in range(n_inputs):\n", - " sleep_sec = random.randint(0, job_time*2000) / 1000 # sleep for random time between 0-2s (avg=1s).\n", - " \n", - " Q.put(function=time.sleep, args=sleep_sec)\n", - "\n", - " Q.waitpb()\n", - "\n", - " results = Q.collect()\n", - "\n", - "title = '{} inputs, 0-2s job time, {} workers (threads).'.format(n_inputs, job_time, n_workers)\n", - "plt = ezpq.Plot(results).build(title=title)\n", - "\n", - "plt.save('imgs/100xNx10.png')\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Timeout\n", - "\n", - "> Recall that you can only use timeout when using processes, not threads." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [], - "source": [ - "n_inputs = 50\n", - "job_time = 1" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4361a5fe28944ba784565f1febad695f", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:706: UserWarning: Saving 6.4 x 4.8 in image.\n", - " from_inches(height, units), units))\n", - "/home/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:707: UserWarning: Filename: imgs/50xNx10_timeouts.png\n", - " warn('Filename: {}'.format(filename))\n" - ] - }, - { - "data": { - "image/png": "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mWf0q1/9Sps3b+72/x8AwDlocAF0auXKlRo/frzKy8slSVOmTFFzc7NWrFjRrftNnz5df/jDH0xrL774Yvt/BwIBTZ48WV988YVef/11rVq1qn0MISYmRvfff/9N719eXq7q6mr9+9//1rBhwyRJEydOVHZ2ttauXas//vGP7dcahqFt27YpPj5e0tVGe9WqVQoEAoqJ4Y0tAIh0/EsOoAO/368DBw5o5syZpvWCgoJu33Pq1Kkd1iorKzVz5kxlZGTI6/WqT58+OnLkiL7++mvL99+7d69+8IMftDe3kpSamqrJkyfr008/NV07ceLE9uZWkoYPH67W1lbV19db/rwAAOfhBBdAB6dPn5bP51N6erppPSMjo9v3vP7PXrx4Ufn5+brjjjv0pz/9STk5OUpISNCiRYvU3Nxs+f7nzp3rtL6MjAx99dVXprV+/fqZPo6Li5Okbn1eAIDz0OAC6OCOO+5QbGxshxPNU6dOmT6Oj49XS0uLae3cuXOd3vPaXzyTpP3796umpkbbt2/XiBEj2tf/+9//disdITU1VUeOHOmwfurUKaWmplq+HwAgcjGiAKADr9erUaNG6d133zWt//WvfzV9nJWVpcrKStParl27uvQ5mpqaJAVPTyXps88+0/Hjx03XxcXF6cqVK7e8X15eng4fPmxqcs+dO6d//OMfysvL61JNAAB3oMEF0Knf/e532rt3rx5//HHt2LFDq1at0saNG03XFBQU6J133tGf//xn7dixQ/Pnz1dtbW2X7n///fcrJSVFS5cu1c6dO1VeXq45c+Zo0KBBpuuGDRsmn8+nV155RRUVFZ2e0krS448/rpycHE2dOlWbN2/We++9p/z8fMXGxurpp5/u3hcBABCRaHABdGr69OkqLS3VRx99pEcffVQ7d+7U22+/bbpm2bJlmjt3roqLi1VYWKicnBw99dRTXbp/RkaG3nnnHdXX12vGjBlau3atysrK9N3vftd03bRp0/TLX/5Sq1ev1n333aclS5Z0er++fftqz549GjFihBYvXqx58+apf//++uSTT0wRYQAA9/MYhmHYXQQAAAAQKpzgAgAAwFVocAEAAOAqNLgAAABwFRpcAAAAuAoNLgAAAFyFBhcAAACuQoMLAAAAV6HBBQAAgKvQ4AIAAMBVaHABAADgKjS4AAAAcJX/ARC2NHRo7QpqAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "with ezpq.Queue(n_workers=n_workers) as Q:\n", - "\n", - " for i in range(n_inputs):\n", - " sleep_sec = random.randint(0, job_time*2000) / 1000 # sleep between 0s and 2s (avg=1s).\n", - "\n", - " Q.put(function=time.sleep, args=sleep_sec,\n", - " timeout=job_time*1.8) # 1.8 < 2; timeout will occur on ~10% of jobs.\n", - "\n", - " Q.waitpb()\n", - "\n", - " results = Q.collect()\n", - " \n", - "title = '{} inputs, 0-2s job time, {} workers (timeout=1.8s).'.format(n_inputs, job_time, n_workers)\n", - "\n", - "plt = ezpq.Plot(results).build(color_by='cancelled',\n", - " color_pal=['blue', 'red'],\n", - " title=title)\n", - "\n", - "plt.save('imgs/{}xNx{}_timeouts.png'.format(n_inputs, n_workers))\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Logging\n", - "\n", - "Writing to a log is as simple as adding `log_file='/path/to/file.csv'`. \n", - "\n", - "The example below illustrates a simply real-world use case. The goal is to obtain the total count and size of files within various folders. One process will be spawned to enumerate each folder. By doing so in parallel, the entire operation only takes as long as the single-most long operation." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Define the function to enumerate the files." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [], - "source": [ - "import os, fnmatch\n", - "def enum_files(path, pattern):\n", - " '''https://stackoverflow.com/a/1724723'''\n", - " n, size = 0, 0\n", - " for root, dirs, files in os.walk(path, followlinks=True):\n", - " for name in files:\n", - " if pattern is None or fnmatch.fnmatch(name, pattern):\n", - " n += 1\n", - " size += os.path.getsize( os.path.join(root, name) )\n", - " \n", - " return (n, size)\n", - "\n", - "root_dir = os.environ['HOME']\n", - "\n", - "include_dirs = [os.path.join(root_dir, x)\n", - " for x in ['bin', 'Desktop', 'Documents', 'Downloads', 'Music', 'Pictures']]" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [], - "source": [ - "log_file = 'ezpq_log.csv'\n", - "\n", - "# first, remove existing log file.\n", - "if os.path.exists(log_file):\n", - " os.unlink(log_file)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Each result will be written to a CSV file and discarded. Afterward, we'll read the CSV back in and draw a plot.\n", - "\n", - "Notice there is no call to `get()` or `collect()`. Because `auto_remove=True`, jobs are discarded; there is no completed queue to pull from." - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "bbd4261aefaf473ebef5582808ccf030", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=6), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Process 3:\n", - "Traceback (most recent call last):\n", - " File \"/usr/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n", - " self.run()\n", - " File \"/usr/lib/python3.6/multiprocessing/process.py\", line 93, in run\n", - " self._target(*self._args, **self._kwargs)\n", - " File \"../ezpq/Queue.py\", line 587, in _job_wrap\n", - " raise ex_obj\n", - " File \"../ezpq/Queue.py\", line 578, in _job_wrap\n", - " out = _job.function(*args, **kwargs)\n", - " File \"\", line 9, in enum_files\n", - " size += os.path.getsize( os.path.join(root, name) )\n", - " File \"/usr/lib/python3.6/genericpath.py\", line 50, in getsize\n", - " return os.stat(filename).st_size\n", - "FileNotFoundError: [Errno 2] No such file or directory: '/home/donald/Documents/Dropbox/pwsh/pskafka/kafkacat-1.4.0RC1/tmp-bootstrap/usr/local/lib/librdkafka++.so'\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "with ezpq.Queue(n_workers = len(include_dirs),\n", - " log_file=log_file, auto_remove=True) as Q:\n", - "\n", - " for path in include_dirs:\n", - " Q.put(name=path,\n", - " function=enum_files,\n", - " kwargs={'path': path, 'pattern': '*'})\n", - "\n", - " Q.waitpb()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Read the CSV file back in with pandas." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
qididnameprioritylanetimeoutfunctionargskwargssubmittedstartedendedprocessedexitcodecancelledruntimeoutputexceptioncallback
0141e2d041/home/donald/bin100NaN0enum_filesNaN{'path': '/home/donald/bin', 'pattern': '*'}2019-02-18 20:21:14.7915652019-02-18 20:21:14.8975352019-02-18 20:21:14.9015912019-02-18 20:21:14.9937350False0.004056(3, 83860646)NaNNaN
1141e2d042/home/donald/Desktop100NaN0enum_filesNaN{'path': '/home/donald/Desktop', 'pattern': '*'}2019-02-18 20:21:14.7915872019-02-18 20:21:14.9038322019-02-18 20:21:14.9089472019-02-18 20:21:14.9947980False0.005115(17, 1162796)NaNNaN
2141e2d045/home/donald/Music100NaN0enum_filesNaN{'path': '/home/donald/Music', 'pattern': '*'}2019-02-18 20:21:14.7916202019-02-18 20:21:14.9263632019-02-18 20:21:14.9303862019-02-18 20:21:14.9952480False0.004023(0, 0)NaNNaN
3141e2d043/home/donald/Documents100NaN0enum_filesNaN{'path': '/home/donald/Documents', 'pattern': ...2019-02-18 20:21:14.7915962019-02-18 20:21:14.9106652019-02-18 20:21:15.0018432019-02-18 20:21:15.0933781False0.091178NaNTraceback (most recent call last):\\n File \".....NaN
4141e2d044/home/donald/Downloads100NaN0enum_filesNaN{'path': '/home/donald/Downloads', 'pattern': ...2019-02-18 20:21:14.7916072019-02-18 20:21:14.9176412019-02-18 20:21:15.0712682019-02-18 20:21:15.0938540False0.153627(4523, 6313058280)NaNNaN
\n", - "
" - ], - "text/plain": [ - " qid id name priority lane timeout function \\\n", - "0 141e2d04 1 /home/donald/bin 100 NaN 0 enum_files \n", - "1 141e2d04 2 /home/donald/Desktop 100 NaN 0 enum_files \n", - "2 141e2d04 5 /home/donald/Music 100 NaN 0 enum_files \n", - "3 141e2d04 3 /home/donald/Documents 100 NaN 0 enum_files \n", - "4 141e2d04 4 /home/donald/Downloads 100 NaN 0 enum_files \n", - "\n", - " args kwargs \\\n", - "0 NaN {'path': '/home/donald/bin', 'pattern': '*'} \n", - "1 NaN {'path': '/home/donald/Desktop', 'pattern': '*'} \n", - "2 NaN {'path': '/home/donald/Music', 'pattern': '*'} \n", - "3 NaN {'path': '/home/donald/Documents', 'pattern': ... \n", - "4 NaN {'path': '/home/donald/Downloads', 'pattern': ... \n", - "\n", - " submitted started \\\n", - "0 2019-02-18 20:21:14.791565 2019-02-18 20:21:14.897535 \n", - "1 2019-02-18 20:21:14.791587 2019-02-18 20:21:14.903832 \n", - "2 2019-02-18 20:21:14.791620 2019-02-18 20:21:14.926363 \n", - "3 2019-02-18 20:21:14.791596 2019-02-18 20:21:14.910665 \n", - "4 2019-02-18 20:21:14.791607 2019-02-18 20:21:14.917641 \n", - "\n", - " ended processed exitcode cancelled \\\n", - "0 2019-02-18 20:21:14.901591 2019-02-18 20:21:14.993735 0 False \n", - "1 2019-02-18 20:21:14.908947 2019-02-18 20:21:14.994798 0 False \n", - "2 2019-02-18 20:21:14.930386 2019-02-18 20:21:14.995248 0 False \n", - "3 2019-02-18 20:21:15.001843 2019-02-18 20:21:15.093378 1 False \n", - "4 2019-02-18 20:21:15.071268 2019-02-18 20:21:15.093854 0 False \n", - "\n", - " runtime output \\\n", - "0 0.004056 (3, 83860646) \n", - "1 0.005115 (17, 1162796) \n", - "2 0.004023 (0, 0) \n", - "3 0.091178 NaN \n", - "4 0.153627 (4523, 6313058280) \n", - "\n", - " exception callback \n", - "0 NaN NaN \n", - "1 NaN NaN \n", - "2 NaN NaN \n", - "3 Traceback (most recent call last):\\n File \"..... NaN \n", - "4 NaN NaN " - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "date_cols = ['submitted', 'started', 'ended', 'processed']\n", - "\n", - "results\n", - "\n", - "df = pd.read_csv(log_file, parse_dates=date_cols)\n", - "\n", - "os.unlink(log_file)\n", - "\n", - "df.head()" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAyEAAAGxCAYAAAB1F7mZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzs3XdUVGf+BvCHKSjg0JGmglGxIgpRbETsBRWMBTSCHVusiRE1rhiN2WgU29piDIuKscVVQcWwa9soFozGElajQXQQlKqABoaZ3x8e7s8RCKDTkOdzDufM3PvOe7/zjpncZ95bjFQqlQpEREREREQ6ItJ3AUREREREVLMwhBARERERkU4xhBARERERkU4xhBARERERkU4xhBARERERkU4xhBARERERkU4xhBARERERkU4xhBARERERkU4xhBARERERkU4xhBARERERkU5J9F3AmygoKEBSUhKaNWsGU1NTfZdDRERElZSTk4OCggKN9GVqagpLS0uN9EVEulUtQ0hSUhK8vLyQmJgIT09PjfWrUqnw7NkzyGQyGBkZaaxfbVKpVFAqlRCJRNWqZo6z9nGctY9jrBscZ93QxTjn5ORgw4YNUCgUGulPIpHg448/ZhAhqoaqZQjRFpVKhby8PNSpU6fa/E8DgPA/uuqC46wbHGft4xjrBsdZN3QxzgUFBVAoFGjbti3q1KnzVn3l5eXhl19+QUFBAUMIUTXEEEJEREQ6VadOHQYHohqu+vxEQ0RERERE7wSGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imGECIiIiIi0ineJ+Q1CoUCCoWi2txgSqVSCXeerS438VIqlQY/zk+U6WrPVSoViouLIVaKq804q5RKPFFmAIXFMDLQcX5ddRtnjrFucJwBO5G9Bqr6a69+NxsbG2t9e0RUszGEvCY7OxticTX6n3PJ/+iqWc2GPs6LCz7Rdwma81DfBdQAHGPdqMHjvMR0tda38ep3s7Ozs9a3R0Q1m8GEkHPnziE6Ohrp6ekwNzfH+PHj0alTJ32XRUREREREGmYQIeTatWvYtm0bPv30UzRr1gxPnz7Fixcv9F0WERERERFpgUGEkOjoaAQGBqJFixYAAEtLSz1XRERERERE2qL3EFJcXIw7d+6gffv2mDx5Ml68eIG2bdtiwoQJMDMz03d5RERERESkYXq/zEhOTg4UCgXOnDmDZcuWYcOGDcjJycG2bdvU2j169AhXrlzBlStX8Ntvv+mpWiIiIiIielt6nwmpVasWAMDPzw+2trYAgGHDhmH58uVq7bZs2YIlS5bovD4iIiIiItIsvc+E1KlTB7a2thVeqnXSpElITExEYmIidu7cqaPqiIiIiIhI0/Q+EwIAvXv3RmxsLN5//33UqlULBw4cQPv27dXaODo6wtHRUU8VEhERERGRphhECBk2bBiePn2KadOmQSwW4/3338eECRP0XRYREREREWmBQYQQsViM0NBQhIaG6rsUIiIiIiLSMr2fE0JERERERDWLQcyEGBIrKyvY2dlBJKoe+UylUkGhUEAikVR4cr+hUCqVKC4uNuhx/kK5Su25SqVCcXExxGJxtRlnlVKJJxkZsLO1hZGBjvPrqts4c4x1g+MM2InqaqCqv/bqdzMRkbYxhLxGIpFAIpEY7M7x61QqFQBUuxBi6OPsCGe159U17EEkhoOxg8GO8+uq2zhzjHWD46wbr343ExFpW/X4NiciIiIioncGQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREekUQwgREREREemURN8FGBqFQgGFQgGRqHrkM5VKBYVCAQAwMjLSczWVo1Qq9TrOSkW62nORxL7C17wL4yyR8D93IiIiMgzcK3lNdnY2xGJxtdnRVKlUKC4urnY163OcC9I/UXtuar+6wte8C+Ps5OSk75KIiIiIAPBwLCIiIiIi0jGGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imGECIiIiIi0imJvgswNFZWVrCzs4NIVD3ymUqlgkKhgEQigZGRkb7LqRSlUoni4mK9jbPSepXac5GkboWv4TgTERERaQ5DyGskEgkkEkm12WlTqVQAUO12jvU6zhLnKr+E40xERESkOdwzISIiIiIinWIIISIiIiIinWIIISIiIiIinWIIISIiIiIinWIIISIiIiIinWIIISIiIiIinWIIISIiIiIinWIIISIiIiIinWIIISIiIiIinWIIISIiIiIinWIIISIiIiIinWIIISIiIqqkMWPGoFWrVjh16hTatm0LMzMztG/fHomJiUKbVatWoV27drCwsEDdunUxYMAA3L59u8x+4uPj0bp1a5iYmKBr165ITk5GVlYWhg8fDnNzczRq1Ah79uwpVUdsbCy8vb1hYmICOzs7TJkyBfn5+Vp//0SawhBCREREVAVpaWmYMWMG5s6di7179+LFixcYPHgwioqKAAAPHz7Exx9/jEOHDmHbtm1QKpXo1KkTsrKySvXzySefYOHChdi1axfu3r2Ljz76CIGBgXB3d8eBAwfg5eWFUaNG4f79+8Lr9u/fj0GDBsHd3R0HDx7EihUr8OOPP2L8+PE6HQeityHRdwFERERE1UlWVhZOnz6Nli1bAgDMzMzQrVs3XLhwAV26dEFERITQtri4GL169ULdunWxf/9+hIaGlttPamoqpk+fjnnz5mHRokUAgHbt2uHHH3/Ev/71L8ycORMqlQqffvopAgMDsW3bNqEvR0dH9O/fH4sWLRL6IzJknAkhIiIiqgInJye1Hf0WLVoAeDkDAgAJCQno1asXbGxsIJFIYGpqiry8vFKHZL3ej5ubGwCgZ8+ewjJLS0vUrVsXDx48AADcvn0b9+/fx/Dhw6FQKIS/rl27QiQS4fLly9p500QaxpkQIiIioiqwtLRU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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# ezpq.Plot requires a dictionary of job data records.\n", - "records = df.to_dict(orient='records')\n", - "\n", - "plt = ezpq.Plot(records).build(color_by='name', bar_width=5)\n", - "\n", - "# plt.save('...')\n", - "plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Callback\n", - "\n", - "If instantiated with a callback, `ezpq.Queue` will pass a dictionary of job data as the single argument to the callback function. It does this synchronously, so the callback must not take too much time." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [], - "source": [ - "def slow_callback(x):\n", - " time.sleep(0.5)" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7302cd202fc24d008dc238022747528e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "with ezpq.Queue(n_workers=n_workers, callback=slow_callback, poll=1) as Q:\n", - " for _ in range(n_inputs):\n", - " Q.put(time.sleep, 1)\n", - " Q.waitpb()\n", - " results = Q.collect()" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": { - "inputHidden": false, - "outputHidden": false - }, - "outputs": [ - { - "data": { - "image/png": "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TI9ZE603B9H61mtOhB6Inrlz57Z6fPHixbr55pvl8Xj08MMPa82aNZbGDakZ6tu3r9555x2NGTNGffr0OeWFsampydIkYonpMWui9eYgWt96zYnQA9EzatSoVo937txZo0aN0qhRo7R+/XrL44bUDD322GMaNGhQ4GPT/lEAAAD2UVVVpcOHDyspKUl9+/bVo48+Gnjt5ptvtjxeSM3QtddeG/j4uuuus/xNnIRovVkrJCbHrInWm1dzwO6qqqq0bNkylZaWyu12y+v1asiQIbrzzjsD55x33nmWx+Wp9RaZGrklWm9uzYnWA7CLFStWaNCgQVq4cKFcLpdqa2v1xBNPaOXKlSosLGzzuPymAwCAmPDFF19o9uzZcrlckiSXy6UbbrhBn332WVjj0gwBAICYkJmZqQMHDgQd83g8yszMDGtctsksMj1mTbTeHKZH6wHYz7Bhw1RQUKDs7OzAEzC2b9+uyZMn69VXXw2cZ/V9EGmGLDI9Zk203hymR+vT0tKiPRUAzezbt09paWnav3+/9u/fL0lKT09XaWmpSktLA+d1WDP06aefBj2O4+yzz7b8jo8AAAChWrx4cUTGtdwMVVdXKz8/X88995x8Pp/i4+NVV1enTp066YorrtCjjz6qHj16RGKutkC03qwVEpNj1qZH6wHYU11dnd5//31VVVUpOTlZZ599trp37x7WmJaboVtvvVWbN2/Wo48+qtzcXPXs2VPHjx/X888/r9tvv1233nqr1q1bF9ak7MzUyC3RenNrbmq0HoD9VFRU6N5771VycrJKSko0aNAgrVu3ToWFhWG9O7zlq/vGjRt1//33a/bs2erZs6ckqWfPnrr++ut13333adOmTW2eDAAAwA957LHHNGPGDC1evFjx8fF68MEHA7tS4bDcDMXHx2vAgAGtvjZw4EDuqAAAQETs27dPEydODDo2ZcqUsN9nyPI22ezZs/XII4/owgsvDFo69/v9WrNmjWbPnh3WhOzO9Jg10Xpz+P1+fV7WYDlBGEvRep5AD8QWn88XuBb7/X5J0t///ne53e6wxg2pGXrooYcCH59++unas2ePBg8erGnTpik5OVmVlZV6+eWXVV9fr/Hjx4c1IbszPWZNtN4cfr9fhctrLX9dLEXreQI9EFv69eunL7/8UhkZGfL7/Xr22Wf12muv6bLLLgtr3JCaoe8/AO37Hn744RbH7r77bs2bNy+sSQEAADSXl5enhoaT7302bNgwVVZW6tZbb9XIkSPDGjekZsjn84X1TZyEaL1ZKySmR+vv+bX1bbJYj9YDsK+zzjor8PE999zTbuPyDtQWmR6zNrEZMrnm/zLIvJoDsK8XX3xRAwcO1IgRIyRJR44c0cGDB4POGT58uOVx29QMeb1ePf7449q5c6cOHz6spKQkjR8/Xtdee23Yf8QEAADQmhdffFH33Xdf4PPq6mrde++96tWrl6STf9f7pz/9yfK4lpuh//u//9PEiRNVXl6ukSNHKiUlRaWlpXr++ef10EMP6c0333T0M31MThaRJjOv5k5Jk5EaA5yhurpaycnJgc/T0tLUq1cvPf7445KkK6+8sk3jWm6GfvWrX0mS/va3vwU9i6y0tFT/+q//ql//+td67rnn2jSZWGBysog0mTk/t+SsNBmpMcAZevTooSNHjui0006TJH3zzTfq0iX8v/ixfKv72muvacmSJS0eyjpkyBAVFhZq69atYU8KAACguaysLK1Zs0aVlZX66quvtHr1amVlZYU9ruV2qrGxUS6Xq9XXXC6Xmpqawp6UnZEmM2uFhDQZaTIA9jFr1iytWLFC+fn5kqSf/exnmjVrVuD1K664ok3jWm6Gxo4dq0WLFik7O1u9e/cOHD927JgWL16ssWPHtmkiscLkZBFpMvNqTpoMgJ306tVL9957r+rr6xUXF9fi7wFzc3PbNK7lZmj58uWaMGGC0tLSdP755yslJUWVlZXatm2bunbtqscee6xNEwEAAAhF9+7d23U8y83Q8OHD9eGHH+p3v/uddu7cqU8++URJSUm66aabdMcdd6h///7tOkEAAIDvbN26Vdu2bdOBAwdUW1srl8ul9PR0TZo0SVOmTGnTmG36E+y0tLSg55WZxOSYNdF682oea9F6IvSAsz399NPasWOHpk+froEDByohIUFer1dlZWV64YUXVFlZqby8PMvjhtQMnXXWWXrmmWc0fPhwjRgx4p9eGOPi4pSUlKQxY8borrvuUlJSkuVJ2ZnJMWui9eb83FJsRuuJ0APO9sorr2j58uVKSUkJOj506FD97Gc/069//evINUOjR48OvLP06NGjT/mPwvHjx/Vf//VfKi0tbdM7QQIAADTX1NSkhITWb7gSEhLU2NjYpnFDaobWrVsX+Pi7d3k8lRdffFHXXHNNmyZlZ0TrzVohIVpPtB6AfYwdO1ZLlizRlVdeqYEDB8rtdsvr9Wr//v3asGFDmxPtEXtQa3Z2tp588slIDR81JsesidabV3Oi9QDs5Oabb9Yzzzyjhx56SN9++638fr/i4uLUq1cvTZo0STNnzmzTuBFrhhITE5WTkxOp4QEAgGG6dOmiWbNmadasWTp27FggTfb99z1sC7NudQEAQEw7ceKEtm3bJq/Xqx/96EdhN0JSBFeGnMrkmDXRevNqbtdoPRF6wFxer1fFxcVKTEzU+eefr9zc3LAf1kozZJHJMWui9eb83JK9o/VE6AGzJSQk6OGHH9b69et1xx13aM6cORo+fHibx6MZAgAAMcXv98vlcun6669XeXm51q5dq9TUVM2ePVu9evWyPB7NkEVE681aISFaT7QegH1s27ZNNTU1amho0LZt2wLHJ0+erG3btumXv/ylnn76acvj0gxZZHLMmmi9eTUnWg/ATrZs2aLGxkbV19dry5YtLV7v169fm8alGQIAADHhgQce0LFjx3TbbbfpgQceaLdxzbrVBQAAMa1379565JFH2nVMVoYsMjlmTbTevJpHM1pPfB5Aa5qamlRaWiqPx6O6ujrFx8crIyNDI0aMUOfObbv+0AxZZHLMmmi9OT+3FP1oPfF5AM0dOHBAixYtUkNDgzIyMpSQkCCv16tNmzapW7duWrBggTIyMiyPSzMEAABiwsqVK3XhhRfq8ssvb/Haxo0bVVRUpAcffNDyuDRDFhGtN2uFhGg90XoA9uHxeLR06dJWX8vJydGGDRvaNG7Um6ETJ05o7dq1+vDDD3X8+HH16dNHM2bMUHZ2tqSTP/iqVatUXl6ulJQU5efna+TIkVGbr8kxa6L15tWcaD0AO0lOTtbu3bs1bty4Fq+9++67SklJadO4UW+GmpqalJSUpEWLFiklJUUlJSX6j//4D6WkpOiMM85QYWGhpkyZoqVLl+rdd9/V0qVLtXbtWiUmJkZ76gAAoAPdfPPNWrJkiTZv3qwBAwbI7XarurpaZWVlOnDggObPn9+mcaN+qxsfH6+ZM2fqRz/6keLi4nTmmWdq6NChKikp0d69e1VfX6/c3Fx17dpV48ePV3p6unbt2hXtaQMAgA42YsQIFRcXKzs7W36/X1VVVZKk7OxsFRcX66yzzmrTuFFfGWqurq5On3/+uaZNm6YDBw4oMzMzaHti4MCB8ng8UZufyTFru0bryw40Wf6aUOPfpkfrTfuZAdhfr169dPHFF7frmLZqhnw+n1asWKHBgwdr1KhR+vTTT+V2u4POcbvdqqysbPG1FRUVqqiokCSVlJREbI4mx6ztGq3/7f01lr8m1Pi36dH65OTkaE8DAILs3r1br7zyiqqqqpSSkqKLLrpIY8aMCWtM29z2+f1+rVmzRocPH9a8efMUFxcnl8slr9cbdJ7X65XL5Wrx9cXFxRo9erRGjx6tvLy8jpo2AADoIDt27NATTzyhCRMm6Ouvv9YeQrOHAAAUm0lEQVSYMWP06KOP6s033wxrXFusDPn9fq1du1ZlZWUqLCwMNDvp6enauHGjfD5fYLm+rKxMEyZMaDHGnDlzNH36dEknV4Yi1RARrbffCknBXda3yUKNf5serQcAO3nhhRd05513asCAAfr973+viy66SGeeeaYefPBBnXfeeW0e1xbNUHFxsUpLS7Vo0SIlJPxj+2LEiBHq1q2bNm3apJycHO3evVsej0djx45tMUZqaqpSU1MjPleTY9Z2jdYPOSNyY5serW9sbIz2NAAgoLKyUgMGDAg6lpaWpq+//jqscaPeDFVWVuq///u/1bVrV11//fWB47m5uZoxY4YWLFigoqIibdiwQcnJyZo/fz6xegAADNS9e3fV1tbK5XIFVq+3bt2qzMzMsMaNejOUnJysl1566Qdfz8zM1LJlyzpwRgAAwI6GDRumjz/+WGeffbaampqUn58vSVqwYEFY40a9GYo1JsesidY7t+Y8IR5ALLj11luDPj799NM1ZMiQNj+t/js0QxaZHLMmWm+vn7s98YR4ALEgPj4+8PH48ePbbVzn3uoCAACEgJUhi4jW22+FhGg9ACAcNEMWmRyzJlpvVs0BwBRc3QEAgNFohgAAgNHYJrPIhJh1a4jWO6PmROgBoCWaIYtMiFm3hmi9M2pOhB4AWor9W10AAIAwsDJkEdF6+62QEK0HAISDZsgiU2PWROvNqzkAmIKrOwAAMBorQxY5KVlkBWmy2Kk5iTEAsIZmyCInJYusIE0WOzUnMQYA1sTGrS4AAECEsDJkEWky+62QkCYDAISDZsgiU5NFpMnMqzkAmIKrOwAAMBrNEAAAMBrbZBbFWsy6vRCtt1/NidADQPugGbIo1mLW7YVovf1qToQeANqHvW51AQAAOhgrQxYRrbffCgnRegBAOGiGLDI1Zk203ryaA4ApuLoDAACj0QwBAACjsU1mkV1j1pFGtD56NSdCDwCRRTNkkV1j1pFGtD56NSdCDwCRZdbyBgAAQDOsDFlEtN5+q2JE6wEA4aAZssjUmDXRevNqDgCm4OoOAACMRjMEAACMxjaZRdGOWUeLk6L1ocbqpY6L1hOfB4DooRmyKNox62hxUrQ+1Fi91HHReuLzABA9Zi1vAAAANMPKkEVE6+23KmY1Wh9qrF4iWg8AJqAZssjUmDXRevNqDgCm4OoOAACMRjMEAACMxjaZRUTridaHgwg9ANgPzZBFROuJ1oeDCD0A2I9ZyxsAAADNsDJkEdF6+62KEa0HAISDZsgiU2PWROvNqzkAmIKrOwAAMBrNEAAAMBrbZBYRrSdaHwoi9AAQO2iGLCJaT7Q+FEToASB2mLW8AQAA0AwrQxYRrbffqhjRegBAOGiGLDI1Zk203ryaA4ApuLoDAACj0QwBAACjsU1mEdF6ovXfR4QeAGIfzZBFROuJ1n8fEXoAiH1mLW8AAAA0Y4uVoc2bN+uNN95QeXm5fvGLX2jevHmB1zwej1atWqXy8nKlpKQoPz9fI0eOjNpcidbbb1WMaD0AIBy2aIaSkpI0Y8YM/e///q+OHz8eON7Y2KjCwkJNmTJFS5cu1bvvvqulS5dq7dq1SkxMjMpcTY1ZE603r+YAYApbXN3PPfdcnXPOOerVq1fQ8b1796q+vl65ubnq2rWrxo8fr/T0dO3atStKMwUAAE5ji5WhH3LgwAFlZmYG3ZEPHDhQHo8nanNqa5oskomnjmDXNBlpLgBAuGzdDNXW1srtdgcdc7vdqqysbHFuRUWFKioqJEklJSURm1Nb02SRTDx1BLumyUhzAQDCZetmyOVyyev1Bh3zer1yuVwtzi0uLlZBQUFHTQ0AADiErZuh9PR0bdy4UT6fL7AtVVZWpgkTJrQ4d86cOZo+fbqkkytDeXl5EZlTW9NkkUw8dQQ7p8kAAAiHLZqhpqYmNTU1yefzyefzBf4mZ8SIEerWrZs2bdqknJwc7d69Wx6PR2PHjm0xRmpqqlJTUyM+17YmiyKZeOoIdk6TAQAQDls0Q88++6w2bNgQ+HzXrl06//zzdfvtt2vBggUqKirShg0blJycrPnz50ctVg8AAJzHFs3Q1VdfrauvvrrV1zIzM7Vs2bIOnhEAADCFLZqhWEK0PjrReiL0AIBIoRmyiGh9dKL1ROgBAJFii3egBgAAiBZWhiwiWk+aDADgLDRDFhGtpxkCADgL22QAAMBoNEMAAMBobJNZRLQ+stF6IvQAgI5GM2QR0frIRuuJ0AMAOhrbZAAAwGisDFlEtJ40GQDAWWiGLCJaTzMEAHAWtskAAIDRaIYAAIDR2CazqC3Requxesn50Xoi9AAAu6AZsqgt0XqrsXrJ+dF6IvQAALtgmwwAABiNlSGL2hKttxqrl4jWAwDQUWiGLGpLtD7WY/US0XoAgHOxTQYAAIxGMwQAAIzGNplFROtDj9YTnwcAxAKaIYuI1ocerSc+DwCIBWyTAQAAo7EyZBHRetJkAABnoRmyiGg9zRAAwFnYJgMAAEajGQIAAEZjm8wiovUto/VE6AEAsYxmyCKi9S2j9UToAQCxjG0yAABgNFaGLCJaT5oMAOAsNEMWEa2nGQIAOAvbZAAAwGg0QwAAwGhsk1lkcrTeys8MAECsoBmyyORofXJycrSnAQBAu+NWHwAAGI2VIYtMjtYDAOBENEMWmRytb2xsjPY0AABod2yTAQAAo7EyZJEJaTIevAoAMAnNkEUmpMl48CoAwCRskwEAAKOxMmSRqWkyAACcimbIIlPTZAAAOBXbZAAAwGg0QwAAwGhsk1nUEdH6jojVE58HAOAkmiGLOiJa3xGxeuLzAACcxDYZAAAwGitDFnVEtJ5YPQAAHYdmyCKi9QAAOAvbZAAAwGg0QwAAwGhsk1kUa9F6IvQAAPxzNEMWxVq0ngg9AAD/HNtkAADAaKwMWUS0HgAAZ4mJZqi6ulqrV6/WX/7yF7lcLl166aXKycmJylyI1gMA4Cwx0QwVFxfrxIkTWrdunSorK3XPPfeof//+Gj16dLSnBgAAYpzt/2aorq5Ou3bt0jXXXKOEhARlZmZqypQpeu2116I9NQAA4AC2b4YOHjwov9+vjIyMwLEBAwbowIEDUZwVAABwCttvk9XV1SkhIThq7na7VVtbG3SsoqJCFRUVkqSSkpIOmx8AAIhttm+G4uPjWzQ+NTU1crlcQceKi4tVUFDQkVMDAAAOYPttsn79+klS0LZYWVmZ0tPTg86bM2eO9uzZoz179uipp57q0DkCAIDYZftmKD4+XmPHjtWTTz6pmpoaeTwebd26VZMnTw46LzU1VVlZWcrKytLQoUOjNFsAABBrbL9NJp1c9SkqKtJ1110nl8ulyy+/nFg9AABoFzHRDPXo0UN33313tKcBAAAcyPbbZAAAAJFEMwQAAIxGMwQAAIxGMwQAAIwWE39AbdV3b9LY3u9E7fP59M033+jQoUOWnlrvBH6/X01NTercubPi4uKiPZ0OQ82puUlMrblkbt3tVvOqqipVVFTom2++CXus6urqkM91ZDNUXl4uScrLy4vuRAAAQJukpqaGPUaXLl1aPNKrNXF+v98f9nezma+//lpbtmxRZmZmi8d2hKOkpER5eXl66qmneGNHQ1Bz81BzM1F3+zh+/Lj69+/fLv9+JyQkKDEx8ZTnOXJlqE+fPpo5c2bExh86dKiysrIiNj7sh5qbh5qbibqbyZyNUQAAgFZ0Xrhw4cJoTyKW9OjRQxMnTlTPnj2jPRV0EGpuHmpuJupuLkf+zRAAAECo2CYDAABGoxkCAABGc2SaLBKqq6u1evVq/eUvf5HL5dKll16qnJycaE8LYdq8ebPeeOMNlZeX6xe/+IXmzZsXeM3j8WjVqlUqLy9XSkqK8vPzNXLkyCjOFuE6ceKE1q5dqw8//FDHjx9Xnz59NGPGDGVnZ0ui5k5WVFSkDz74QLW1terZs6emTJmiGTNmSKLukORHSJYtW+YvLCz0e71ef1lZmT8vL8//wQcfRHtaCNOuXbv877zzjv+RRx7xP/DAA4HjJ06c8N9www3+Z5991t/Q0OB/6623/FdeeaX/yJEjUZwtwlVbW+t/6qmn/BUVFX6fz+f/5JNP/FdeeaW/pKSEmjucx+Px19XV+f1+v7+ystI/d+5c/44dO6g7/H6/38/KUAjq6uq0a9cu/e53v1NCQoIyMzM1ZcoUvfbaaxo9enS0p4cwnHvuuZKk/fv36/jx44Hje/fuVX19vXJzc9WpUyeNHz9eL7/8snbt2qWpU6fq73//u1atWqUvvvhCnTt3Vlpamu67775o/RgIUXx8fNB7kJ155pkaOnSoSkpKVFtbS80dLD09PejzuLg4HTp0iN91SGKbLCQHDx6U3+9XRkZG4NiAAQP0zjvvRHFWiKQDBw4oMzMz6BlFAwcOlMfjkSQ9+eST6tevnwoKCiRJpaWlUZknwlNXV6fPP/9c06ZNo+YG+MMf/qDNmzervr5eycnJOu+88/T2229Td/AH1KGoq6tr8WwTt9sdeCAsnKe2tlZutzvo2Pdr3qVLFx0+fFiVlZXq0qWLhg0bFo1pIgw+n08rVqzQ4MGDNWrUKGpugGuvvVbPPfecli9fruzs7EB9qTtohkIQHx/fovGpqalp1+eewV5cLpe8Xm/QMa/XG6j57NmzlZSUpAULFuimm27SCy+8EI1poo38fr/WrFmjw4cPa968eYqLi6PmhoiLi9PgwYPVtWtXrV+/nrpDEttkIenXr5+kk1sn3+07l5WVtdiDhnOkp6dr48aN8vl8geXzsrIyTZgwQZKUmJiouXPnSjr590b33HOPBg8eTAIlBvj9fq1du1ZlZWUqLCwM/KNHzc3i8/lUUVGhrKws6g5WhkIRHx+vsWPH6sknn1RNTY08Ho+2bt2qyZMnR3tqCFNTU5MaGhrk8/nk8/nU0NCgxsZGjRgxQt26ddOmTZt04sQJ7dy5Ux6PR2PHjpUk7dy5U1VVVZJOLql36tQp6G8OYF/FxcUqLS1VQUFB0PY3NXeu6upqvfnmm6qpqZHP59Pf/vY3vfLKK/rpT39K3SGJx3GErLq6WkVFRYH3Gbrssst4nyEHeOaZZ7Rhw4agY+eff75uv/12lZeXq6ioSOXl5UpOTtacOXMCd4OPP/64/ud//kfV1dXq2bOnLrroosB7lsC+KisrdeONN6pr167q3Llz4Hhubq5mzJhBzR2qurpaS5cu1f79++Xz+ZSUlKQLLrhAl112meLi4qg7aIYAAIDZWOsDAABGoxkCAABGoxkCAABGoxkCAABGoxkCAABGoxkCAABGoxkCAABGoxkCAABGoxkCELKjR48qLi5Ojz/+eId9z+3bt2vJkiUtji9cuFA9evTosHkAcC6aIQC29kPN0I033qg333wzCjMC4DQ8tR5Ah6utrQ08Lb6t+vfvr/79+7fTjACYjJUhAD/o0UcfVWZmphISEjRp0iR9/vnnQa/HxcVp2bJlQcdWrFihuLi4wOfbt29XXFyc/vznPys3N1e9evXSFVdcIUl64oknNG7cOCUlJem0007TxIkT9d577wW+duHChSooKJDX61VcXJzi4uI0ceLEwGvNt8k8Ho9yc3PVu3dvud1uXXjhhdq7d2/QOZmZmbrlllu0evVqZWRkqHfv3rrkkksCTyYHYB5WhgC0avPmzcrPz9d1112nq666Snv27Ak0MW2Rn5+vvLw8/fGPfww8Mb68vFyzZs3SoEGD1NDQoPXr12vChAn66KOP9C//8i+68cYb9eWXX+qZZ57RG2+8IUnq1atXq+MfP35cEydOVKdOnbR27VrFx8dr8eLFgfHS0tIC57700kv67LPPtHr1an399de64447dOutt2rDhg1t/vkAxC6aIQCtWrRokcaPH69169ZJki688ELV1dWpsLCwTeNNnz5d999/f9Cxe++9N/Cxz+fT5MmT9d577+nxxx/XkiVLAlthnTp10jnnnPNPx1+3bp08Ho8++eQTDR06VJKUnZ2t9PR0rVixQsuXLw+c6/f79dJLL6l79+6STjZlS5Yskc/nU6dOLJgDpuG3HkALTU1N2rNnjy699NKg47m5uW0ec+rUqS2OlZSU6NJLL1VKSoo6d+6srl27qrS0VJ9++qnl8Xfs2KHhw4cHGiFJSkpK0uTJk7Vz586gc7OzswONkCSdeeaZOnHihCorKy1/XwCxj5UhAC1UVVWpsbFRycnJQcdTUlLaPGbzrz1+/LimTJmivn376qGHHlJGRobi4+N14403qq6uzvL4R44caXV+KSkp+vjjj4OOJSYmBn3erVs3SWrT9wUQ+2iGALTQt29fdenSpcVKyVdffRX0effu3dXQ0BB07MiRI62O+f0/qpakd955R19++aU2b96skSNHBo4fO3asTSmxpKQklZaWtjj+1VdfKSkpyfJ4AMzBNhmAFjp37qysrCz98Y9/DDr+wgsvBH3ev39/lZSUBB177bXXQvoetbW1kv6xKiNJb7/9tsrLy4PO69atm+rr60853rhx47R3796ghujIkSN6/fXXNW7cuJDmBMBMNEMAWvWb3/xGO3bs0OzZs7VlyxYtWbJETz75ZNA5ubm5ev7557Vy5Upt2bJF11xzjQ4ePBjS+Oecc4569Oihf/u3f9PWrVu1bt06XXXVVerXr1/QeUOHDlVjY6Mefvhhvf/++62u/kjS7NmzlZGRoalTp2rDhg3605/+pClTpqhLly66/fbb2/YfAYARaIYAtGr69Olau3attm3bpksuuURbt27Vs88+G3TOPffco6uvvloFBQXKy8tTRkaGbrvttpDGT0lJ0fPPP6/Kykrl5ORoxYoVKi4u1hlnnBF03rRp0zR37lwtXbpUP//5zzVnzpxWx+vZs6e2b9+ukSNHKj8/XzNnztRpp52mt956KyhWDwDNxfn9fn+0JwEAABAtrAwBAACj0QwBAACj0QwBAACj0QwBAACj0QwBAACj0QwBAACj0QwBAACj0QwBAACj0QwBAACj0QwBAACj0QwBAACj0QwBAACj/X81yBD+0UsFJAAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ezpq.Plot(results).build(show_legend=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Error Handling" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "def reciprocal(x):\n", - " time.sleep(1)\n", - " return 1/x\n", - "\n", - "with ezpq.Queue(n_workers=5, job_runner=threading.Thread) as Q:\n", - " for _ in range(20):\n", - " Q.put(reciprocal, random.randint(0, 5), suppress_errors=True)\n", - " Q.wait()\n", - " output = Q.collect()" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[{'qid': '873bf141',\n", - " 'id': 5,\n", - " 'name': 5,\n", - " 'priority': 100,\n", - " 'lane': None,\n", - " 'timeout': 0,\n", - " 'function': 'reciprocal',\n", - " 'args': [0],\n", - " 'kwargs': None,\n", - " 'submitted': datetime.datetime(2019, 2, 18, 20, 21, 55, 726351),\n", - " 'started': datetime.datetime(2019, 2, 18, 20, 21, 55, 827401),\n", - " 'ended': datetime.datetime(2019, 2, 18, 20, 21, 56, 828921),\n", - " 'processed': datetime.datetime(2019, 2, 18, 20, 21, 56, 830606),\n", - " 'exitcode': -1,\n", - " 'cancelled': False,\n", - " 'runtime': 1.0015199184417725,\n", - " 'output': None,\n", - " 'exception': 'Traceback (most recent call last):\\n File \"../ezpq/Queue.py\", line 578, in _job_wrap\\n out = _job.function(*args, **kwargs)\\n File \"\", line 3, in reciprocal\\n return 1/x\\nZeroDivisionError: division by zero\\n',\n", - " 'callback': None},\n", - " {'qid': '873bf141',\n", - " 'id': 6,\n", - " 'name': 6,\n", - " 'priority': 100,\n", - " 'lane': None,\n", - " 'timeout': 0,\n", - " 'function': 'reciprocal',\n", - " 'args': [0],\n", - " 'kwargs': None,\n", - " 'submitted': datetime.datetime(2019, 2, 18, 20, 21, 55, 726363),\n", - " 'started': datetime.datetime(2019, 2, 18, 20, 21, 56, 830782),\n", - " 'ended': datetime.datetime(2019, 2, 18, 20, 21, 57, 832082),\n", - " 'processed': datetime.datetime(2019, 2, 18, 20, 21, 57, 834327),\n", - " 'exitcode': -1,\n", - " 'cancelled': False,\n", - " 'runtime': 1.0012998580932617,\n", - " 'output': None,\n", - " 'exception': 'Traceback (most recent call last):\\n File \"../ezpq/Queue.py\", line 578, in _job_wrap\\n out = _job.function(*args, **kwargs)\\n File \"\", line 3, in reciprocal\\n return 1/x\\nZeroDivisionError: division by zero\\n',\n", - " 'callback': None},\n", - " {'qid': '873bf141',\n", - " 'id': 15,\n", - " 'name': 15,\n", - " 'priority': 100,\n", - " 'lane': None,\n", - " 'timeout': 0,\n", - " 'function': 'reciprocal',\n", - " 'args': [0],\n", - " 'kwargs': None,\n", - " 'submitted': datetime.datetime(2019, 2, 18, 20, 21, 55, 726513),\n", - " 'started': datetime.datetime(2019, 2, 18, 20, 21, 57, 835738),\n", - " 'ended': datetime.datetime(2019, 2, 18, 20, 21, 58, 836210),\n", - " 'processed': datetime.datetime(2019, 2, 18, 20, 21, 58, 838107),\n", - " 'exitcode': -1,\n", - " 'cancelled': False,\n", - " 'runtime': 1.000471830368042,\n", - " 'output': None,\n", - " 'exception': 'Traceback (most recent call last):\\n File \"../ezpq/Queue.py\", line 578, in _job_wrap\\n out = _job.function(*args, **kwargs)\\n File \"\", line 3, in reciprocal\\n return 1/x\\nZeroDivisionError: division by zero\\n',\n", - " 'callback': None},\n", - " {'qid': '873bf141',\n", - " 'id': 16,\n", - " 'name': 16,\n", - " 'priority': 100,\n", - " 'lane': None,\n", - " 'timeout': 0,\n", - " 'function': 'reciprocal',\n", - " 'args': [0],\n", - " 'kwargs': None,\n", - " 'submitted': datetime.datetime(2019, 2, 18, 20, 21, 55, 726524),\n", - " 'started': datetime.datetime(2019, 2, 18, 20, 21, 58, 838259),\n", - " 'ended': datetime.datetime(2019, 2, 18, 20, 21, 59, 839682),\n", - " 'processed': datetime.datetime(2019, 2, 18, 20, 21, 59, 841945),\n", - " 'exitcode': -1,\n", - " 'cancelled': False,\n", - " 'runtime': 1.0014238357543945,\n", - " 'output': None,\n", - " 'exception': 'Traceback (most recent call last):\\n File \"../ezpq/Queue.py\", line 578, in _job_wrap\\n out = _job.function(*args, **kwargs)\\n File \"\", line 3, in reciprocal\\n return 1/x\\nZeroDivisionError: division by zero\\n',\n", - " 'callback': None}]" - ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "[x for x in output if x['exception'] is not None]" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [], - "source": [ - "# for x in output:\n", - "# if x['exception'] is not None:\n", - "# x['exitcode'] = 1\n", - "# else:\n", - "# x['exitcode'] = 0" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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l16qmTNnNttO0KNHD61du1azZ8/W7NmzJUk1NTU699xzJUkPPvigbr31Vq1YsULt2rXToEGDdPfdd6t79+6SpLfffltXXnmlamtr5ff7NWzYMN1yyy2qqKhIZ/7Pf/6jSy65RM8884xat26tcePGpX9Z7qtisZiuv/56PfPMM4pGozr88MM1c+ZMDR8+vMD/qs1RYnMUi8Xk9/tdd+fj5jtW27ZdOTdmlqmqpqrAqVAI9uTi3GuH4vTvf/9bU6ZMSW8fKCkp0XnnnaexY8c6nOy/li1bpiFDhujkk0/W448/rq1bt+qGG27QyJEjtWzZMl122WX685//rLFjx2r58uUKBAI6++yzdfDBB2vq1Km7POczzzyjk08+WVVVVfrlL38pSTrooIMkSb///e919dVX67zzztOMGTOUSCS0ePFibdiwQd27d9cnn3yi4447TgcddJAefvhhNTU1adKkSRo8eLDeeusttW/fXpI0fvx4LVy4UL/5zW/Us2dP3XXXXXr00UczcsTjcQ0bNkyff/65ZsyYoQMOOEAPP/ywTjnlFL322mvq169fAf9lm6PEAgAAI/To0UMff/xxusBJ0tq1a9WjRw/nQn3Ntddeq+9+97t6+umn0w/C+/Xrp8MPP1zPPvusTj75ZM2bN09HHHGErr/+enXq1EnLly9XXV2dgsHgLs85YMAAtWrVSqWlpRnbDDZt2qQpU6ZowoQJmjt3bvr4yJEj0x/feuutSiQSev755xUOh9Pn69u3r+bNm6dLL71U7733np5++mndd999Gj9+vCTphBNOUK9evTJyPPLII3rjjTf05ptvqm/fvunrffDBB5o2bZqeeOKJPPwLZo8Sm6NQKKRIJOKqp6Wl/z417bbVSmnnU9PJZNJ1c2NmmWrH1RY4VX64eQU9vZ0gkv12AiAXhx12mKZOnarBgwerU6dO2rBhg5YsWaJhw4bpueeeS1/vxBNPdCTftm3btHTpUs2aNUupVCp9vHfv3urWrZvq6up08sknq3v37qqurtZ5550nv9+v6dOn79Eq5rJly7Rt2zadd95533idV155RUOHDk0XWEk65JBD1L9/f9XW1urSSy9VXV2dbNvWaaedlr6Oz+fTqFGjdOutt6aPPf/88+rXr5969+6tZDKZPj5s2DA9/PDDOeffW5TYHAUCAQWDQVeVIWnnHavX63VtIXLj3JhZJlP2Vrr9wUdDoEFlZWWuuq2heKxcuVLdunXT6tWrtXr1aklSRUWFVq1apVWrVqWv51SJ3bhxo1KplK644gpdccUVzS7/5JNP0h+PHDlSl1xyiVKplC644II9+n6NjY2SpC5dunxrpu985zvNjpeWlioajUqS6uvrFQgE1KFDh2bX+aovvvhCr7/+esarQXzJ5/PlnH9vUWIBAIARZsyY4XSEbxUKheTxeHT99ddr1KhRzS7v2LFj+uOLLrpIHTp0UCKR0OWXX64HHngg5+8XiUQkSevWrVPXrl13eZ1wOLzLdzr7/PPP1bt3b0k7X9IrkUho48aNGUX2888/b3auI444Qn/4wx9yzloIlFgAAIA8aNu2rY4++mitWLFC06dP/8brzZ8/X48//riee+45NTU1adSoUTrttNN2WXy/FAwG1dTUlHHs6KOPVps2bVRTU6NBgwbt8uuqqqp0zz33ZBTUVatW6a233krvf/3e974naecvkH15LJVK6U9/+lPGuX74wx/q2WefVZcuXb519belZFVie/bsmdPTXl8u8QMAAOTL1KlTNXny5Ixj06ZN04033uhQouZ+//vfa+jQofrpT3+qM844Qx06dNCnn36qRYsWady4cerdu7cuvvhiXXjhhTrhhBMkSeecc44mTJigY445ZpcvayVJhx56qBYvXqxFixapQ4cO6tmzpyKRiCZPnqxrrrlGlmVp5MiRsixLL774ov7nf/5H3/3ud3XFFVeopqZGw4cP16RJk9TU1KQbbrhBFRUV6Zfo6tu3r0477TRdfvnlampqUo8ePXTXXXcpHo9nZDj77LM1d+5cDRkyRFdeeaV69+6tWCym119/XfF4XDNnzizov+3XZbVpaeTIkRl/EomEGhsbNWDAAJ144okaMGCAGhsblUwmv/VRBAAAwJ467LDDmh378rfki8Uxxxyj2tpabdmyRePGjdPJJ5+sX//612rTpo0OPvhgnXfeeerQoYNmzZqV/prbb79dJSUlmjhx4jee96abblLXrl314x//WN/73vf017/+VZJ09dVX6/7779eyZct02mmn6dxzz9X777+fLsPdunXTSy+9pA4dOuiss87ShAkT1L9/fy1ZsiT98lqSdP/992vEiBG6+uqrdfbZZ6tPnz66/PLLMzK0atVKixcv1o9+9CPNmDFDw4cP10UXXaR//etfqqpq+Zc59Ng5viHu73//ez3zzDN67rnntN9++6WPb9q0SSeddJJGjhypa665Ju9Bc/Haa6/pyCOP1PLlyzVw4MC8ndeyLDU0uPOXFlz/yyYunBszMxNzM5Nb51ZsM1u3bp3uueceHXvssQqFQnt1rlgspldeeUUTJkwoiqe+kX85/4+9/fbbdd1112UUWEnaf//9de211+qOO+7IWzgAAABgV3IusdFoVJs2bdrlZZs2bdLGjRv3OhQAAADwbXIusccff7yuueYavfTSSxnHlyxZomuvvVbHH3983sIBAACYwLbtgv3BruX8Eltz587ViBEjNHToUO2///7pd8zYtGmTBgwYoDlz5hQiJwAAQNH66KOPCvJsdJcuXVReXp7387pBziW2vLxcdXV1eu655/TPf/5T9fX1Ki8v16BBgxx7hwwAALBvaGho0OrVq1VRUZF+gf/Gxkbtt99+u3wnKbjXHr/ZwYknnkhpBQAALWbZsmWqrq5W586dVV9fr6uvvlovvfSSli5dqtatW+u6665T//79Hc345btg5cP777+ft3O5UVYlNhqNKhQKyev1pt9n99uEw+G9DgYAAPBVjz32mK655hoNHDhQy5cv12233aYxY8bosssu0+LFi/XAAw/olltucTomWkhWJbZTp05atmyZBg0apI4dO+72NfJSqVRewhWjRCKheDxeFK+nl09fvgaiZVmueg1EaefrILpxbswsU11DXYFT5Ydt20qlUvL5fO6bm20p2hhVOBGW15Pd3CorKgucCm6yYcOG9Ou/Dxw4UJs3b9ZJJ50kn8+nE088UfPmzXM2IFpUViX2/vvv10EHHZT+2G0/eHMRi8Vc92LXkrvvWG3bduXcmFmmqpqWf7cY7D17Mr95jey1atVKjY2NikQi+uKLL2Tbtj777DNVVFRo3bp1ateundMR0YKyKrHnnHNO+uMv32cXAACgJR111FG66aabVFVVpVdeeUVnnHGGpkyZoj59+ui9997Tj370I6cjOqK+vl4TJ07Uv/71L9XX12vFihU65JBDnI5VcHv8i137qlAopEgk4qqnpSX3vqWitPOp6WQy6bq5MbNMteNqC5wqP9y8gp7eThDJfjsBkIvzzjtPTzzxhN59910NHz5cJ554oo488ki9/vrrGjJkiL7//e87HdERXq9XJ554om644YZ9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L7ygQCCg+++/P+cQZ555ps4888xdXtajRw/NmjUr53MCAAB3+fjjj3XAAQdkHOvataujr1oE5+T8PN3hhx+uN998U+eff77WrVunxYsXa926dbrgggv05ptv6vDDDy9ETgAAsI/r1auX7rvvPm3ZskXSzl/2vvfee/O6+glz7NHrxHbr1k233HJLvrMAAAB8o8suu0w333yzxo4dq5KSEm3fvl19+/bVL3/5S6ejwQFZldgjjjhCjz76qA4//HD169fvW3+JxOPxKBwOa9CgQbrmmmsUDofzFhYAAOy7OnbsqJkzZyoajaqxsVHhcFiRSMTpWI6IxWKaMGGC/v73v6t9+/a6+uqrdfnllzsdq0VlVWKPPPLI9JsOHHnkkbv9TejNmzfrD3/4g1atWqU//elPe58SAADg/4TD4YxFsuuuu04zZ850MFHLu+SSS7Rjxw599tlnWrt2rY4//nj16dNHJ510ktPRWkxWJbampib98bx587I68Z///Gf97Gc/26NQAAAAX/dNrxO7cuVK3XjjjSotLdXpp5+uLl26tHCylrV161Y9+eSTWr58ufbbbz/169dPF1xwge6//35KbD4MHjxYDz30UKFODwAA9jHHHnvsLo+vWrVKlZWVWrt2rWbNmuXI7+1MfnWyHn7/4byfd92Edc2Ovf/++7IsK+OX6b/zne/o6aefzvv3L2YFK7GhUEgjR44s1OkBAMA+5sQTT9zl8ZqamvRlZ5xxRktGcsSWLVsyXqtf2tm7Nm/e7FAiZ/BWOAAAwGhffZvZ008/3cEkLaNdu3b6z3/+k3Fs06ZNat++vUOJnEGJBQAARnjnnXdk23az4wcffLA++OADvf322xozZowDyVpW79695fF49O6776aPvfHGG/vca/UXbDsBAABAPk2aNEl//OMfFQgEml322WefadGiRerXr58DyaSp35+qy3tf3iJvO9u2bVuNHj1akyZN0kMPPaS1a9fqvvvuy/hF/H0BJRYAABjB4/HonXfe2WWJTSaTWr16tQOpnDF79mxdcMEFKi8vV/v27XXttdfuU69MIFFic5ZIJBSPx+X1umsnhm3bSiaTsixrt68DbBrLsnKaW11DXQuk2nu2bSuVSsnn87lvZralaGNU4URYXk92t7XKisoCpwJQDKqrq7/xZ16rVq1aOI1zQqGQnnzySadjOIoSm6NY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qcSef/75evHFFx1IBAAoBn6nAwDY92zfvl0lJSV7dY6uXbuqa9eueUoEADANK7EAvtG9996rHj16qE2bNjr++OP14YcfZlzu8Xg0a9asjGPV1dXyeDzpz5csWSKPx6O//e1vGj16tPbbbz/95Cc/kSQ9+OCDqqqqUjgcVocOHTRkyBD985//TH/tlClTNHXqVG3dulUej0cej0dDhgxJX/b17QRr167V6NGjtf/++6tt27Y64YQT9Pbbb2dcp0ePHrrkkks0e/Zsde/eXfvvv79GjRqlDRs27PW/FwCg5bASC2CXFixYoAkTJujcc8/VGWecoeXLl6fL556YMGGCxo4dq2eeeUY+n0+StGbNGp199tk66KCDFI/H9dhjj+m4447TW2+9pd69e+v888/Xp59+qkcffVSLFy+WJO233367PP/mzZs1ZMgQeb1ezZkzR61bt9aMGTPS5+vWrVv6un/5y1/0wQcfaPbs2friiy90xRVX6NJLL9X8+fP3+O8HAGhZlFgAuzR9+nQde+yxqqmpkSSdcMIJampq0rRp0/bofCNGjNBvf/vbjGO/+tWv0h9blqVhw4bpn//8p+bNm6ebbropvWXA6/XqqKOO+tbz19TUaO3atXr33Xd16KGHSpIGDx6siooKVVdX6+abb05f17Zt/eUvf1GrVq0k7SzTN910kyzLktfLE1QAYAJ+WgNoJpVKafny5TrttNMyjo8ePXqPz3nKKac0O7ZixQqddtppKi0tlc/nUyAQ0KpVq/T+++/nfP5XXnlFhx9+eLrASlI4HNawYcNUW1ubcd3BgwenC6wk9e3bV4lEQuvXr8/5+wIAnMFKLIBmNmzYoGQyqc6dO2ccLy0t3eNzfv1rN2/erOHDh6tTp0665ZZb1L17d7Vu3Vrnn3++mpqacj7/xo0bd5mvtLRU77zzTsaxUCiU8XkwGJSkPfq+AABnUGIBNNOpUyf5/f5mK5Off/55xuetWrVSPB7POLZx48ZdnvOrv+wlScuWLdOnn36qBQsWqH///unjmzZt2qNXHQiHw1q1alWz459//rnC4XDO5wMAFDe2EwBoxufzaeDAgXrmmWcyjv/xj3/M+Lxr165asWJFxrFFixZl9T22b98u6b+roJL0v//7v1qzZk3G9YLBoHbs2LHb81VVVentt9/OKLIbN27UP/7xD1VVVWWVCQBgDkosgF2aNGmSXnnlFY0bN04LFy7UTTfdpIceeijjOqNHj9aTTz6p22+/XQsXLtTPfvYzffbZZ1md/6ijjlK7du108cUX6/nnn1dNTY3OOOMMHXDAARnXO/TQQ5VMJnXbbbeprq5ul6utkjRu3Dh1795dp5xyiubPn68//elPGj58uPx+vy6//PI9+0cAABQtSiyAXRoxYoTmzJmjF154QaNGjdLzzz+vxx9/POM6N954o84880xNnTpVY8eOVffu3XXZZZdldf7S0lI9+eSTWr9+vUaOHKnq6mrNnTtXBx98cMb1Tj31VF100UWaOXOmvv/972vixIm7PF/79u21ZMkS9e/fXxMmTNBZZ52lDh066OWXX854eS0AgDt4bNu2nQ4BAAAA5IKVWAAAABiHEgsAAADjUGIBAABgHEosAAAAjEOJBQAAgHEosQAAADAOJRYAAADGocQCAADAOJRYAAAAGIcSCwAAAONQYgEAAGAcSiwAAACM8/8BZ+N0VYYUZHQAAAAASUVORK5CYII=\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ezpq.Plot(output).build(color_by='exitcode', color_pal=['red', 'green'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Shared Objects" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [], - "source": [ - "def fibonacci(shared):\n", - " shared_clone = tuple(shared)\n", - " shared[0] = shared[1]\n", - " shared[1] = sum(shared_clone)\n", - " return shared[1]" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1,\n", - " 2,\n", - " 3,\n", - " 5,\n", - " 8,\n", - " 13,\n", - " 21,\n", - " 34,\n", - " 55,\n", - " 89,\n", - " 144,\n", - " 233,\n", - " 377,\n", - " 610,\n", - " 987,\n", - " 1597,\n", - " 2584,\n", - " 4181,\n", - " 6765,\n", - " 10946]" - ] - }, - "execution_count": 39, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import multiprocessing as mp\n", - "mgr = mp.Manager()\n", - "shared_list = mgr.list([0,1])\n", - "\n", - "with ezpq.Queue(n_workers=10) as Q:\n", - " for _ in range(20):\n", - " Q.put(fibonacci, args=shared_list)\n", - " Q.wait()\n", - " output = Q.collect()\n", - "\n", - "mgr.shutdown()\n", - " \n", - "[x['output'] for x in output]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# New in v0.2.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `tqdm` Integration" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Add `show_progress=True` to `ezpq.Queue()`; this works for `map()` and the `@decorator`" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [], - "source": [ - "with ezpq.Queue(5, show_progress=True) as Q:\n", - " output = Q.map(time.sleep, range(5))" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f21ab39826574cd0b41bd14d4fdbb18e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "@ezpq.Queue(n_workers=5, show_progress=True)\n", - "def time_sleep(x):\n", - " time.sleep(x)\n", - "\n", - "output = time_sleep(range(5))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Or add `show_progress=True` to `ezpq.map()`" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "cc51eb73e523441f836b1840dc76551c", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "with ezpq.Queue(5) as Q:\n", - " output = Q.map(time.sleep, range(5), show_progress=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Or add `show_progress=True` to `ezpq.Queue.wait()`" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "beaf4092a03d406dac81d506653c5e39", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "with ezpq.Queue(5) as Q:\n", - " for i in range(5):\n", - " Q.put(time.sleep, i)\n", - " Q.wait(show_progress=True)\n", - " output = Q.collect()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Or just call `ezpq.Queue.waitpb()` in place of `ezpq.Queue.wait()`." - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": {}, - "outputs": [], - "source": [ - "from random import random" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f27ed6344a8f4d03b692affa5817615b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "with ezpq.Queue(5) as Q:\n", - " for i in range(50):\n", - " Q.put(time.sleep, random())\n", - " Q.waitpb()\n", - " output = Q.collect()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## map" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3422853d24e74e37ac7c31e3a1c638b9", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=1000), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "text/plain": [ - "['0^2 = 0',\n", - " '1^2 = 1',\n", - " '2^2 = 4',\n", - " '3^2 = 9',\n", - " '4^2 = 16',\n", - " '5^2 = 25',\n", - " '6^2 = 36',\n", - " '7^2 = 49',\n", - " '8^2 = 64',\n", - " '9^2 = 81']" - ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "def my_pow(x, k):\n", - " return '{}^{} = {}'.format(x, k, x**k)\n", - "\n", - "with ezpq.Queue(10, show_progress=True) as Q:\n", - " output = Q.map(my_pow, iterable=range(1000), args=2, show_progress=True)\n", - " \n", - "[x['output'] for x in output[:10]]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Synchronous Lanes" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [], - "source": [ - "jobs = {\n", - " 'Lane 1': [1,2,3],\n", - " 'Lane 2': [4,5,6],\n", - " 'Lane 3': [7,8,9],\n", - " 'Lane 4': [10,11,12],\n", - " 'Lane 5': [13,14,15],\n", - " 'Lane 6': [16,17,18]\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b1a67e1276c14d6986ef0f00225bb8ec", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=18), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "with ezpq.Queue(n_workers=3) as Q:\n", - " for lane in jobs.keys():\n", - " for job in jobs[lane]:\n", - " Q.put(time.sleep, args=1,\n", - " lane=lane, name='Job '+str(job))\n", - " Q.waitpb()\n", - " output = Q.collect()" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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1Ztvvskl7A+aNWuWnnjiCZWVlcnhcKiqqkoVFRXh/dnZ9eebPjRLu3fvXpWXlysUCik3Nze8/9BpFY8kLS1N48aNk9/v17p169ShQ4coPqPDa3GQXbduXYNL1Pbr108nnnhiNGsDAABo0llnnaXMzEwtWLBAL7/8sk466SRNmDDB6rIst2zZMs2YMUOLFy9Wr1695HQ61a5du2atW83Ly5Pb7VZ5eXmLLqJiGIb279+vbdu2JW6Q3bt3r8aOHauXX35ZhmEoKSlJNTU1cjqdGjZsmB577DGlpqbGolYAANCKvfTSSw3u9+zZU/fdd5/3OORvAAAgAElEQVRF1TQ05cdTNLHHxLheojYYDDb4Qyyn06nq6mq53W75/X4Fg0HNnDlTVVVVzTpedna2ioqKNGHCBE2fPl0+n09bt27V559/riFDhjR6/F/+8hedcMIJ6tmzp6qqqnT77berffv2OumkkyJ7okch4jWy48eP18KFC/XYY49pz5492r9/v/bs2aNHH31Ub731lsaPHx+LOgEAAPA948ePV3Jycvhr0KBBGjx4sIqKitSzZ0916dJFHo+nwVKBI3n66afl8XjUu3dvZWRkaPDgwYcN1N98840uvfRSpaWlqUePHtq2bZveeecdJSUlRespHpHDjPAcCenp6fr973+vX/7yl432PfLII7rjjju0Z8+eqBXYEqtWrVJ+fr4+/fRT9enTJ2rjGoahHTt2cF5IcUGE76Mv6tEX9eiLevRFPfqiXlN9UVZWpkcffVRnn312k6faHDNmjEaMGKEBAwY02vf666/L4XBo6NChkg5cUn7ZsmUaO3ZsXC7RvH79eu3evTvqM7I5OTlxOU++XUX8vygpKanB6S6+77jjjuMvBgEAQEzs2rVLjz/+uJYsWdJo3+mnn64PPvgg/kXBUhEH2VGjRukPf/hDo0XDpmnqkUce0ahRiXm5SAAAYG8ej0e//e1v9dRTT2nx4sUN9nXt2lXl5eUWVQarNOuPvR544IHw7aysLH366ac64YQTdMkll6hDhw4qLy/Xm2++qe+++05nn312zIoFAACtW7du3TR16lTddddd2rdvn37yk59IkiorK5WWlmZxdYi3ZgXZm2++ucntDz30UKNtt99+u2655ZajqwoAAOAwcnNzNX36dN19991atWqVevXqpaVLl2rgwIFWl4Y4a9bS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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 49, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ezpq.Plot(output).build(color_by='lane',\n", - " color_pal=['blue', 'red', 'green',\n", - " 'purple', 'orange', 'brown'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Set the lane based on an expression." - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1e19f7d5676243a4a50b31e872bbe0b7", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=20), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "image/png": "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CQlxlciQkBDVqmVdrbntttssO7ZVKJEAAMAnvPjii5oxY4YWL16st99+W7NmzdLKlSvldDr1xz/+Ue+9957VEf3KRZfIvXv3VnjsYadOndSyZUt3ZgMAAHDZsGGD8vPzdc8996hNmzaqVauWJk6cqCNHjujdd9/V4sWLLcu2cuVKfffdd24ft1u3burTp4/bx3UH4xJZUFCg5ORkvfHGGyovL1dwcLCKi4sVEBCg22+/XS+99FK1Xr8HAAC+a/v27Ro9erSk00/IKy4uVmFhocWppAMHDsjpdLp93B9++MHtY7pLgOkH7rvvPqWmpuqll15Sfn6+CgsLlZ+frxdffFFr1qzRfffd54mcAAAAstlsuvLKK9WnTx81aNCgWhRIf2V8JvKtt97S008/rZEjR7q21alTR6NGjVJxcbEee+wxLVmyxK0hAQAA6tWrp+eff16RkZFq0KCBcnNzlZWVpXHjxik3N9fqeH7H+ExkcHCwmjVrds73mjdvrsDAwEsOBQAA8GsPPPCAPv30U9188806efKkbrzxRm3ZskXjx4+3OppfMi6RI0eO1AsvvFBp3d/pdGrBggUVzlACAAC4S+fOnbV8ecVnuP/tb39Thw4dLErk36q0nD1r1izXz5dddpm2b9+uK664QgMHDlT9+vWVlZWlf/7znyopKVH37t09FhYAAPiv4OBglZScfiqUzWaTJEVGRurUqVNWxvK6kpISjRkzRuvXr1dOTo7i4+P1+OOPu57m4y1VKpHnO008e/bsStseffRRPfLII0YhUlNTtWHDBqWnpyspKanC5zMyMjR37lylp6crNjZWycnJat++vdH4AADA9/34449q3LixDh8+LJvNphtuuEFDhw7Vu+++a3U0ryorK1PDhg21fv16NWvWTJs3b9aAAQPUrFkzJSUleS1HlZazy8vLq/zL4XAYh4iKitKQIUN0/fXXV9heVlamqVOnqnPnznr99dd1xx13aObMmcrLyzM+BgAA8G0vv/yyYmJiJElHjhzRH/7wB7355pt66aWXLE7mXWFhYZoyZYqaN28um82mbt26qWvXrvrss8+8mqNaPLHmmmuukXT6HksnTpxwbd+1a5dKSko0ePBgBQQEqHv37vrnP//patwAAMB/rFu3zvXzf/7nf1qYpLKrTx3W5c6f3T7uJiVccJ+TJ0/qiy++0AMPPOD2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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 50, - "metadata": {}, - "output_type": "execute_result" + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# `ezpq` Examples" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "%matplotlib inline" + ], + "outputs": [], + "execution_count": 1, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "code", + "source": [ + "import sys\n", + "import os" + ], + "outputs": [], + "execution_count": 2, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "if os.path.exists('../ezpq/__init__.py'):\n", + " sys.path.insert(0, '../')\n", + "import ezpq" + ], + "outputs": [], + "execution_count": 3, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "import os\n", + "import time\n", + "import random\n", + "import logging as log\n", + "import multiprocessing as mp\n", + "import threading\n", + "logger = log.getLogger()\n", + "logger.setLevel(log.INFO)\n", + "# logger.setLevel(log.DEBUG) # uncomment to view verbose output" + ], + "outputs": [], + "execution_count": 4, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "code", + "source": [ + "import pandas as pd\n", + "from datetime import datetime" + ], + "outputs": [], + "execution_count": 5, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "# Context manager to time functions\n", + "class MyTimer():\n", + " '''https://www.blog.pythonlibrary.org/2016/05/24/python-101-an-intro-to-benchmarking-your-code/'''\n", + " def __init__(self):\n", + " self.start = time.time()\n", + "\n", + " def __enter__(self):\n", + " return self\n", + "\n", + " def __exit__(self, exc_type, exc_val, exc_tb):\n", + " end = time.time()\n", + " runtime = round(end - self.start, 3)\n", + " msg = 'Runtime: {time}'\n", + " print(msg.format(time=runtime))" + ], + "outputs": [], + "execution_count": 6, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Elementary example\n", + "\nI'll start with a step-by-step example to illustrate the basic operations. The code below is what we want to optimize. It simply loops 10 times, sleeping 1 second each time, for a total of 10 seconds." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "```python\n", + "for _ in range(10):\n", + " time.sleep(1)\n", + "```" + ], + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Create the Queue with *n* workers." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "Q = ezpq.Queue(n_workers=5)" + ], + "outputs": [], + "execution_count": 7, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Put jobs in the Queue." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "for _ in range(10):\n", + " Q.put(time.sleep, 1)" + ], + "outputs": [], + "execution_count": 8, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "size() will count all jobs in the waiting, working, and completed queues." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "Q.size()" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 9, + "data": { + "text/plain": [ + "10" + ] + }, + "metadata": {} + } + ], + "execution_count": 9, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Create a list to store job data (runtime and output)." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "results = list()" + ], + "outputs": [], + "execution_count": 10, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "`get()` is used to pop the highest priority job from the *completed* queue. The result must be stored or it will be lost.\n", + "\nWhen no output is available and `wait` is true, the operation will wait for the next job to finish." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "done = Q.get(wait=True) # get() returns a dict\n", + "\nresults.append(done) # append dictionary to results list." + ], + "outputs": [], + "execution_count": 11, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Count remaining jobs after the operation above." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "Q.size()" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 12, + "data": { + "text/plain": [ + "9" + ] + }, + "metadata": {} + } + ], + "execution_count": 12, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "`collect()` is used to repeatedly `get()` all completed jobs.\n", + "\n", + "`collect()` does not support the `wait` parameter;\n", + "\nInstead, wait for all running and queued jobs to complete with `wait()` before calling `collect()`." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "Q.wait()\n", + "\n", + "done_list = Q.collect() # collect() returns a list\n", + "\nresults.extend(done_list) # extend result list " + ], + "outputs": [], + "execution_count": 13, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Verify no jobs remain." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "Q.size()" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 14, + "data": { + "text/plain": [ + "0" + ] + }, + "metadata": {} + } + ], + "execution_count": 14, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Dispose of the `ezpq`. This will ensure all jobs are stopped and data is discarded." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "Q.dispose()" + ], + "outputs": [], + "execution_count": 15, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Now, inspect a single job result." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "results[0]" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 16, + "data": { + "text/plain": [ + "{'qid': '9030a545',\n", + " 'id': 1,\n", + " 'name': 1,\n", + " 'priority': 100,\n", + " 'lane': None,\n", + " 'timeout': 0,\n", + " 'function': 'sleep',\n", + " 'args': [1],\n", + " 'kwargs': None,\n", + " 'submitted': datetime.datetime(2019, 3, 12, 23, 54, 52, 228484),\n", + " 'started': datetime.datetime(2019, 3, 12, 23, 54, 52, 324976),\n", + " 'ended': datetime.datetime(2019, 3, 12, 23, 54, 53, 332575),\n", + " 'processed': datetime.datetime(2019, 3, 12, 23, 54, 53, 368588),\n", + " 'exitcode': 0,\n", + " 'cancelled': False,\n", + " 'runtime': 1.007598876953125,\n", + " 'output': None,\n", + " 'exception': None,\n", + " 'callback': None}" + ] + }, + "metadata": {} + } + ], + "execution_count": 16, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Create a pandas dataframe for a grid view of the results." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "df = pd.DataFrame(results)\n", + "\ndf.head()" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 17, + "data": { + "text/plain": [ + " args callback cancelled ended exception exitcode \\\n", + "0 [1] None False 2019-03-12 23:54:53.332575 None 0 \n", + "1 [1] None False 2019-03-12 23:54:53.336425 None 0 \n", + "2 [1] None False 2019-03-12 23:54:53.341192 None 0 \n", + "3 [1] None False 2019-03-12 23:54:53.345096 None 0 \n", + "4 [1] None False 2019-03-12 23:54:53.350268 None 0 \n", + "\n", + " function id kwargs lane name output priority processed \\\n", + "0 sleep 1 None None 1 None 100 2019-03-12 23:54:53.368588 \n", + "1 sleep 2 None None 2 None 100 2019-03-12 23:54:53.369051 \n", + "2 sleep 3 None None 3 None 100 2019-03-12 23:54:53.369197 \n", + "3 sleep 4 None None 4 None 100 2019-03-12 23:54:53.369314 \n", + "4 sleep 5 None None 5 None 100 2019-03-12 23:54:53.454563 \n", + "\n", + " qid runtime started submitted \\\n", + "0 9030a545 1.007599 2019-03-12 23:54:52.324976 2019-03-12 23:54:52.228484 \n", + "1 9030a545 1.007510 2019-03-12 23:54:52.328915 2019-03-12 23:54:52.228505 \n", + "2 9030a545 1.007855 2019-03-12 23:54:52.333337 2019-03-12 23:54:52.228516 \n", + "3 9030a545 1.007642 2019-03-12 23:54:52.337454 2019-03-12 23:54:52.228524 \n", + "4 9030a545 1.008313 2019-03-12 23:54:52.341955 2019-03-12 23:54:52.228532 \n", + "\n", + " timeout \n", + "0 0 \n", + "1 0 \n", + "2 0 \n", + "3 0 \n", + "4 0 " + ], + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
argscallbackcancelledendedexceptionexitcodefunctionidkwargslanenameoutputpriorityprocessedqidruntimestartedsubmittedtimeout
0[1]NoneFalse2019-03-12 23:54:53.332575None0sleep1NoneNone1None1002019-03-12 23:54:53.3685889030a5451.0075992019-03-12 23:54:52.3249762019-03-12 23:54:52.2284840
1[1]NoneFalse2019-03-12 23:54:53.336425None0sleep2NoneNone2None1002019-03-12 23:54:53.3690519030a5451.0075102019-03-12 23:54:52.3289152019-03-12 23:54:52.2285050
2[1]NoneFalse2019-03-12 23:54:53.341192None0sleep3NoneNone3None1002019-03-12 23:54:53.3691979030a5451.0078552019-03-12 23:54:52.3333372019-03-12 23:54:52.2285160
3[1]NoneFalse2019-03-12 23:54:53.345096None0sleep4NoneNone4None1002019-03-12 23:54:53.3693149030a5451.0076422019-03-12 23:54:52.3374542019-03-12 23:54:52.2285240
4[1]NoneFalse2019-03-12 23:54:53.350268None0sleep5NoneNone5None1002019-03-12 23:54:53.4545639030a5451.0083132019-03-12 23:54:52.3419552019-03-12 23:54:52.2285320
\n", + "
" + ] + }, + "metadata": {} + } + ], + "execution_count": 17, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Lastly, visualize the steps." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "ezpq.Plot(results).build()" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "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evfu7QvKkuRyuTRs2DC9//77fvsOHjzYF5QlqWfPnqqtrVVxcXGDbxcAEF6YWQZwVkePHpXb7VaHDh38tqekpDR6zB9et7y8XFdeeaXat2+vuXPnqnPnzoqOjtb48eNVXV3d4PG/+eabOutLSUnRrl27/LYlJib6/R4ZGSlJjbpdAEB4ISwDOKv27dvL6XSeMdN65MgRv9+joqJUU1Pjt+2bb76pc8zvf+lPkj766CN9/fXXWrdunfr06ePbXlZW1qijXLhcLu3Zs+eM7UeOHJHL5WrweACA1ollGADOyuFwqF+/flq7dq3f9ldeecXv9/T0dBUUFPht27BhQ71u48SJE5K+m9WVpA8//FD79u3z2y8yMlInT54863iXX365du7c6ReYv/nmG7399tu6/PLL61UTAACEZQD18sADD+i9997TuHHjtH79es2aNUvLly/322fUqFFavXq1nnnmGa1fv14333yzDhw4UK/xL730UsXHx+vf//3f9dZbb2np0qW64YYbdM455/jt16NHD7ndbj399NP6+OOP65w9lqRx48apc+fOuuaaa7Rq1Sq99tpruvLKK+V0OnXvvfc27kEAALQ6hGUA9TJixAgtXrxYGzdu1LXXXqu33npLL730kt8+Dz74oEaPHq28vDyNGTNGnTt31j333FOv8VNSUrR69WoVFxdr5MiRmj9/vvLz85WVleW33/Dhw3XHHXdo9uzZuuSSSzRx4sQ6x0tISNCmTZvUp08fTZgwQTfddJPatWunf/zjH36HjQMA4MfYDMMwrC4CAAAACEbMLAMAAAAmCMsAAACACcIyAAAAYIKwDAAAAJggLAMAAAAmCMsAAACACcIyAAAAYIKwDAAAAJggLAMAAAAmCMsAAACACcIyAAAAYIKwDAAAAJj4f40PUy9XHeVkAAAAAElFTkSuQmCC\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 18, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 18, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "In the chart above, the colored lines overlap because the jobs were run in parallel. Contrast that with the following example using serial processing." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Practical Examples" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Shared parameters; adjust as desired." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "n_workers = 10 # number of workers to process the queue.\n", + "n_inputs = 50 # number of inputs to the queue.\n", + "job_time = 1 # number of seconds each input will 'sleep'" + ], + "outputs": [], + "execution_count": 19, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + "---" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(n_workers=n_workers) as Q: # create an ezpq.Queue() with 10 workers. \n", + " for i in range(n_inputs): # create 50 jobs, each sleeping for 1 second.\n", + " Q.put(function=time.sleep, args=job_time)\n", + " \n", + " Q.waitpb() # wait for all jobs to complete.\n", + " \n", + " results = Q.collect() # collect completed jobs from queue.\n", + " \n", + "df = pd.DataFrame(results)\n", + "\ndf.head()" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "88b0a8ca0cca4b14be29c36c6ebd7ed8" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + }, + { + "output_type": "execute_result", + "execution_count": 20, + "data": { + "text/plain": [ + " args callback cancelled ended exception exitcode \\\n", + "0 [1] None False 2019-03-12 23:54:57.786251 None 0 \n", + "1 [1] None False 2019-03-12 23:54:57.791527 None 0 \n", + "2 [1] None False 2019-03-12 23:54:57.796455 None 0 \n", + "3 [1] None False 2019-03-12 23:54:57.800084 None 0 \n", + "4 [1] None False 2019-03-12 23:54:57.805892 None 0 \n", + "\n", + " function id kwargs lane name output priority processed \\\n", + "0 sleep 1 None None 1 None 100 2019-03-12 23:54:57.813994 \n", + "1 sleep 2 None None 2 None 100 2019-03-12 23:54:57.814404 \n", + "2 sleep 3 None None 3 None 100 2019-03-12 23:54:57.814531 \n", + "3 sleep 4 None None 4 None 100 2019-03-12 23:54:57.814645 \n", + "4 sleep 5 None None 5 None 100 2019-03-12 23:54:57.814780 \n", + "\n", + " qid runtime started submitted \\\n", + "0 163e44b7 1.007813 2019-03-12 23:54:56.778438 2019-03-12 23:54:56.670451 \n", + "1 163e44b7 1.008554 2019-03-12 23:54:56.782973 2019-03-12 23:54:56.670491 \n", + "2 163e44b7 1.008746 2019-03-12 23:54:56.787709 2019-03-12 23:54:56.670502 \n", + "3 163e44b7 1.007728 2019-03-12 23:54:56.792356 2019-03-12 23:54:56.670517 \n", + "4 163e44b7 1.008828 2019-03-12 23:54:56.797064 2019-03-12 23:54:56.670532 \n", + "\n", + " timeout \n", + "0 0 \n", + "1 0 \n", + "2 0 \n", + "3 0 \n", + "4 0 " + ], + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
argscallbackcancelledendedexceptionexitcodefunctionidkwargslanenameoutputpriorityprocessedqidruntimestartedsubmittedtimeout
0[1]NoneFalse2019-03-12 23:54:57.786251None0sleep1NoneNone1None1002019-03-12 23:54:57.813994163e44b71.0078132019-03-12 23:54:56.7784382019-03-12 23:54:56.6704510
1[1]NoneFalse2019-03-12 23:54:57.791527None0sleep2NoneNone2None1002019-03-12 23:54:57.814404163e44b71.0085542019-03-12 23:54:56.7829732019-03-12 23:54:56.6704910
2[1]NoneFalse2019-03-12 23:54:57.796455None0sleep3NoneNone3None1002019-03-12 23:54:57.814531163e44b71.0087462019-03-12 23:54:56.7877092019-03-12 23:54:56.6705020
3[1]NoneFalse2019-03-12 23:54:57.800084None0sleep4NoneNone4None1002019-03-12 23:54:57.814645163e44b71.0077282019-03-12 23:54:56.7923562019-03-12 23:54:56.6705170
4[1]NoneFalse2019-03-12 23:54:57.805892None0sleep5NoneNone5None1002019-03-12 23:54:57.814780163e44b71.0088282019-03-12 23:54:56.7970642019-03-12 23:54:56.6705320
\n", + "
" + ] + }, + "metadata": {} + } + ], + "execution_count": 20, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "code", + "source": [ + "title='{} inputs, {}s job time, {} workers (parallel).'.format(n_inputs, job_time, n_workers)\n", + "\n", + "plt = ezpq.Plot(results).build(title=title)\n", + "\n", + "plt.save('imgs/{}x{}x{}.png'.format(n_inputs, job_time, n_workers))\n", + "plt" + ], + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "/Users/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:706: UserWarning: Saving 6.4 x 4.8 in image.\n", + " from_inches(height, units), units))\n", + "/Users/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:707: UserWarning: Filename: imgs/50x1x10.png\n", + " warn('Filename: {}'.format(filename))\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "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\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 21, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 21, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Job Priority" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Jobs are prioritized by (1) custom priority and (2) arrival time. By using a priority queue for both pending and completed jobs, you can be sure that higher priority jobs are executed and retrieved sooner.\n", + "\nThe default priority value is 100. Lower values take higher priority." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(n_workers=n_workers) as Q:\n", + "\n", + " for i in range(n_inputs):\n", + " Q.put(function=time.sleep, args=job_time,\n", + " priority=int((i+1) % 10 != 0)+1) # prioritize numbers divisible by ten.\n", + "\n", + " Q.waitpb()\n", + "\n", + " results = Q.collect()\n", + "\n", + "title = '{} inputs, {}s job time, {} workers (prioritized).'.format(n_inputs, job_time, n_workers)\n", + "\n", + "plt = ezpq.Plot(results).build(title=title, color_by='priority')\n", + "\n", + "plt.save('imgs/100x1x10_priority.png')\n", + "plt" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "b253d5779858467a8cbb325db0e9db4a" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "/Users/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:706: UserWarning: Saving 6.4 x 4.8 in image.\n", + " from_inches(height, units), units))\n", + "/Users/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:707: UserWarning: Filename: imgs/100x1x10_priority.png\n", + " warn('Filename: {}'.format(filename))\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "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/PHHH+jWrRsGDRqERYsW4eLFi1i2bBliY2Nx6tQp2NkZvwdZvnw5fv/9d0yaNAleXl7YuXMnkpKScOnSJWzcuFHx/bdo0QIbN27EqFGj0LVrVyQkJBjdfuHCBcTExMDX1xeTJ09GQEAAbty4gZMnT+Lf//43Bg8eXK2fW4lvv/0WAwYMQMuWLTF9+nR4e3vjzz//xNGjR/HDDz+ga9euio/5xx9/oGPHjsjKysKECRMQGRmJn376CatXr8aePXvwn//8B35+fkbfI/PYL126FMnJyTh06JDRvp07d6601lmzZuHevXt4/vnnYW9vj/feew+xsbHYunUrxo8fj+HDh2PgwIH497//jY8//hjOzs5YtWqV4fvv3LmDqKgo/PrrrxgzZgwiIyORk5OD1atX44knnsChQ4fQrl07hY+gcteuXUNGRgY6d+4MV1dXo9tCQkLg7++P7777rsJjODo6omvXrjhw4AD0er3h+ZGamgo7OzscPXoUhYWFcHFxMWx3d3fHE088AeB+Y/bUU0/hwIEDeOqppzB16lT8+eefWLlyJaKiorB792706NHD6D5PnDiBrVu3Yty4cXj22WfLfTMrhMDMmTPx9ttv44UXXkBycrKhvh9//BHR0dFwc3PDuHHjEBwcjIsXL2LlypXYv38/vvvuO3h6ehod77nnnoODgwOmTJkCDw8PRERESD8fv//+e9y5c8fs61kZpeO87DrxmTNnQq/X46GHHir32GvWrEF8fDyCgoIwffp0eHh4YOvWrZg6dSp++uknfPTRR9U+/saNGzF//nzcuHEDS5YsMWxv0aKF2f19fHzM/jwHDx7EmjVrjO5nz549GDx4MAIDAzFt2jT4+fnhp59+QnJyMo4cOYIDBw4YZmO///57dOvWDfb29pg2bRoCAwPx1VdfITo6Gnl5eWZr6dChA5ycnHDgwAFMmzat3MePSNPUvpbAlnXo0EEsXLhQbNu2TXz66adi8uTJwtHRUXh5eYmzZ88a7evh4SF8fX3NHmf69OkCgPjpp58qvU9z1xYFBwcLAOLTTz812r5w4UIBQOzdu9ewrexaPjc3N5Genm7YXlpaKgYPHmxyrVtF11rBzPWk5rYJIcR7770nAIhjx45V+jNWV1paWoXXmL700ksCgPjzzz+rdfw5c+YIACItLc2wrey6xk8++cRo348//tikFqWP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3wsAiB4aUwADTJs2TYmJiQN2EG/duhX2ODk5Wb29vWFjnZ2dg875nxeiJOn8+fNqbm7WsWPHNGfOnND4r7/+GtFt+/T0dF27dm3A+K1bt5Senm55PgDA6OMoH8AATqdTeXl5OnLkSNj4xx9/HPY4IyNDDQ0NYWMnTpwY1u/o6emR9NdupSR98803un79etjzkpKS9Mcff/y/8+Xn5+vKlSthzWlnZ6e+/PJL5efnD6smAEBs0ZgCGNTrr7+us2fPas2aNTp+/LgqKyt14MCBsOeUlJTo8OHDevfdd3X8+HGtWrVKN27cGNb88+bNU2pqql588UXV1dWptrZWK1as0MyZM8Oel5ubq7t372r37t26ePHioLuikrRmzRplZWVp0aJFOnTokD799FMVFRUpMTFRr7zySmR/CQCAUUVjCmBQS5YsUU1NjU6ePKlly5aprq5OH330UdhztmzZotLSUlVUVKisrExZWVnauHHjsOb3er06fPiwWltbtXTpUlVVVcnn8+m+++4Le97ixYv1wgsv6K233tKjjz6qDRs2DDrfxIkTdebMGc2ZM0fr16/XypUrlZaWpq+++iosKgoAYC5HMBgMxroIAAAAgB1TAAAAGIHGFAAAAEagMQUAAIARaEwBAABgBBpTAAAAGIHGFAAAAEagMQUAAIARaEwBAABgBBpTAAAAGIHGFAAAAEagMQUAAIAR/gVY1m/9A+ucUwAAAABJRU5ErkJggg==\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 22, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 22, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Threads\n", + "\n", + "By default, `ezpq.Queue` uses `multiprocessing.Process` to spawn new jobs. However, you can use `threading.Thread` instead by specifying `job_runner=Thread` when creating the Queue. Some of the differences between processes and threads are explained [here](https://medium.com/@bfortuner/python-multithreading-vs-multiprocessing-73072ce5600b).\n", + "\n", + "> Note that, inherently, `Thread` loses the ability to enforce a timeout, to kill jobs, or to obtain exit codes.\n", + "\n", + "Aside from that, there's no difference in how you interact with ezpq.\n", + "\nIn addition to using Threads, the example below varies the job time between 0-2 seconds." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "from threading import Thread\n", + "\n", + "with ezpq.Queue(n_workers=n_workers, job_runner=Thread) as Q:\n", + "\n", + " for i in range(n_inputs):\n", + " sleep_sec = random.randint(0, job_time*2000) / 1000 # sleep for random time between 0-2s (avg=1s).\n", + " \n", + " Q.put(function=time.sleep, args=sleep_sec)\n", + "\n", + " Q.waitpb()\n", + "\n", + " results = Q.collect()\n", + "\n", + "title = '{} inputs, 0-2s job time, {} workers (threads).'.format(n_inputs, job_time, n_workers)\n", + "plt = ezpq.Plot(results).build(title=title)\n", + "\n", + "plt.save('imgs/100xNx10.png')\n", + "plt" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "a0346d73f9394f4bb70f040a4b35d9e9" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "/Users/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:706: UserWarning: Saving 6.4 x 4.8 in image.\n", + " from_inches(height, units), units))\n", + "/Users/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:707: UserWarning: Filename: imgs/100xNx10.png\n", + " warn('Filename: {}'.format(filename))\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "iVBORw0KGgoAAAANSUhEUgAAAsQAAAHICAYAAABJf/xlAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzs3Xl8TPf+P/DXZN/FZJGEbFJNxVZLU4pEbKUILW35llpaQUtbRVFrSu1UQy1VpaXlVlXdq5e0YiuuLkqrElRF7JJKRTYhmfP7I7+ZZsxkOefM5Mzyej4eHg8558yZt5Nj5j2f+ZzXUQmCIICIiIiIyE45KF0AEREREZGS2BATERERkV1jQ0xEREREdo0NMRERERHZNTbERERERGTX2BATERERkV1jQ0xEREREdo0NMRERERHZNTbERERERGTX2BDbmIiICHTq1EnpMkiGixcvQqVSYfbs2ZL3URvngUqlwrBhw8z6HFS1Tp06ISIiQukyJHnnnXcQEBCA/Pz8Gm2/ceNGqFQqHDhwwLyFmZHU/5ebNm2Cm5sbLl68aPKaiKgcG2IzUqlUlf75/fffDbYvLS3FwoULER0dDVdXV4SEhGDMmDG4deuWAtWbx+zZs/H111/X6nMWFRVhypQpiIiIgKurKyIiIjB16lQUFRXVeB9//PEHZs+ejfbt2yMoKAienp6IiYnBa6+9huvXr5uxeuVcvHgRs2fPxsmTJ5UuxaQ+/PBDDBkyBE2aNIGTkxNUKhWuXLmidFl25cqVK1i4cCGmTp0Kb29v3fIDBw5g9uzZuH37toLVWZ4XXngBUVFRmDRpktKlENksJ6ULsHUdO3ZEUlKSwfLQ0FCDZcOHD8fmzZvRu3dvTJw4EZmZmVi+fDkOHz6MY8eOwdPTs9rnO3v2LFQqlUlqN4fk5GQMHToU/fr1q5XnKysrw1NPPYWDBw9iyJAhiIuLw6+//orFixfjxx9/xHfffQcHh+o/F65fvx4rV65Enz598Nxzz8Hd3R3Hjh3DqlWrsHnzZhw9ehSPPPKISWoODw9HcXExnJyU/e958eJFJCcnIyIiAo8++qjB+uLiYjg6OipQmTzz5s3DX3/9hUcffRQRERH4888/lS7J7ixatAgODg4YNWqU3vIDBw4gOTkZw4YNg6+vr0LVWR4HBwe88cYbSEpKwu+//46mTZsqXRKRzWFDbGYNGzbE4MGDq91u37592Lx5MxITE7Fz507d8tatW2PAgAFYunQpZs6cWe1+XF1dZdVraz755BMcPHgQ48aNQ0pKim55REQEJk6ciM2bN+PFF1+sdj8DBgzAlClT9N6kk5KS0LZtW4waNQozZ87EF198YZKaVSoV3NzcTLIvc7KGGo3Zv38/wsPD4eDggGHDhlldQywIAgoLC+Hl5VWrz3vnzh34+PjI3k9BQQE++eQTPPvsszX6kG9KxcXFcHZ2VvzDphTPPfccXnvtNaxatQqrVq1Suhwim8MpE7Xg/v371c6T+/TTTwEAb775pt7y/v37IyIiQre+OsbmqGmXnTt3Dn379kWdOnXg5eWFp556CufPn9fb9sCBA1CpVNi4cSNWr16Nxo0bw83NDREREZg9ezZKS0v1tq9qDmPFOaba/QLlTWrF6SNax44dQ58+fRASEgJXV1cEBwcjISFB1hQL7XGbMGGC3vJXXnkF7u7uNT6ubdq0MTpiNXDgQADAb7/9prf8ypUrSEpKQmRkJNzc3ODv74/WrVtj3rx51T5XZXOINRoNUlJS0KJFC7i7u8PHxwedO3fGd999V+m+fv31V3Tv3h3e3t6oU6cOnnnmmRo1gLNnz0ZCQgKA8m8utL+riueWsTnE2mWHDh1Chw4d4OnpiXr16mHy5MkoKytDSUkJpkyZgtDQULi5ueGxxx7DsWPHjNawfft2xMfHw8fHB+7u7mjZsiU++uijamuvTmRkZI2+FajM559/DpVKhf/85z96y2NiYqBSqbBp0ya95U888QQaNmyot+zMmTMYOHAg6tWrB1dXVzRs2BATJ07EnTt39LbTzpvdu3cv5s+fj4cffhiurq5YsmRJpfXl5+ejR48ecHV1xebNm/XW1fSYal8zfvvtN/Tq1Qt169ZFnTp1AJQ35CtWrEDLli11ryVRUVH4v//7vxpNH9qzZw/u3LmDXr166S3v1KkTkpOTAZT/jrTn3IP/DwRBwPLly3XHIjIyEsuWLTN4Hu1rU1ZWFgYOHAh/f394eHjoTY+p6fH49ttvMWjQIERFRen+78XFxRmcA1rHjx9H165d4enpibp166J///6Vzv/ds2cPOnfujMDAQLi5uaFBgwbo2bMnvv/+e73t6tSpgw4dOmDbtm0QBMHovohIOuv7mGxlvvzyS2zevBllZWWoU6cOevfujblz5xo0kT/88AMcHBzQtm1bg320a9cOW7ZsQW5uLtRqtaQ6rl69iri4OCQmJmLhwoX4448/sGLFCvTt2xenTp0yaBBWrlyJK1euYPTo0VCr1di5cyeSk5Px559/Grzh10Tjxo2xadMmDBkyxOg0knPnzqFLly4IDAzEK6+8gpCQEPz11184fvw4/ve//0maYiEIAn766SeEhIQgPDxcb527uzseffRR/PTTT6L3W9HVq1cBAPXq1dMtKy0tRbdu3XD58mWMGTMGjzzyCAoKCnDmzBns27cPb7/9tqTnGjZsGDZt2oT27dtj3rx5KCgowEcffYQnn3wSn376qcE3EVeuXEFCQgISExOxaNEiZGRkYM2aNTh69CiOHz+O+vXrV/pczzzzDO7fv4958+YhKSkJHTt2NPh3VubEiRPo168fXnrpJQwePBj//e9/sWjRIjg6OuLUqVO4c+cOJk6ciMLCQixduhS9e/dGZmam3lzSWbNm4Z133kFCQgJmzZoFd3d3pKamYuTIkTh//jwWLFgg6RiaQpcuXQAAe/fuRZ8+fQAA165dQ0ZGBhwcHLB3714MGTIEQPmo6k8//YThw4frHn/y5EnExcWhtLQUr7zyCho2bIjDhw9j6dKlSEtLw5EjR+Dh4aH3nJMmTUJRURGGDh2KgIAAo1OutHU89dRTuHjxIvbs2aP7UAOIP6aXL19GfHw8nn76acyfPx83btwAUD7lZPr06Xjqqafw8ssvw8XFBZcuXcKePXtw7do1BAcHV3n89u/fDwAGr3XTpk2DWq3Gjh078N5778Hf3x8A0Lx5c73t3n77bdy5cwfDhw+Hl5cXPv30U0yYMAEhISG6D6haBQUF6NixIx577DEkJycjPz9fN7Iu5nhs3LgRN2/exODBg9GgQQPk5OTgk08+QWJiIrZu3Yrnn39et+0vv/yCuLg4ODo6Yty4cQgNDcW3336LTp06obCwUK++Q4cOoXfv3oiJicGkSZPg5+eHGzdu4OjRozhx4oTu/53WE088gb179+LUqVMGx4WIZBLIbNq0aSPMnz9f2L59u/D5558Lr7zyiuDs7Cyo1WohIyNDb1svLy8hMDDQ6H4mTZokABB+/fXXap8zPDxciI+PN1gGQPj888/1ls+fP18AIKSmpuqW7d+/XwAgeHh4CBcvXtQtLysrE/r16ycAEPbv369bHh8fL4SHhxutBYAwdOjQapcJgiC8//77AgDh2LFj1f4ba+qvv/4SAAixsbFG1z/77LMCACEvL0/yc/Tv318AIGzYsEG37NdffxUACAsWLJC0z8zMTAGAMGvWLN2ytLQ0AYDQs2dPobS0VLc8OztbCAwMFHx9fYX8/Hzdcu3vfPHixXr7/uqrryr9HTxIey5U/LdVVNnvV6VSCUePHtVb/uijjwoqlUro1auXoNFodMt37NghABDWrl2rW/bLL78IKpVKeO211wyec+zYsYKDg4Pw559/Vlt/TQwdOlQAIFy+fFnU45o2bSrExMTofv7kk08ElUolDBkyRKhfv75u+c6dOwUAwtatW3XLOnbsKKhUKuHw4cN6+0xOThYACHPmzNEt27BhgwBAiIqK0vv9alX8/3fq1CkhNDRUCA0NFU6dOqW3ndhjqj1/Vq9ebbB9y5YthcaNG1d2aKoVHx8vuLm5GV03a9YsAYCQmZlpsE57LJo3by7cvXtXt7ygoEDw8/MT2rVrZ/A8AITJkycb7Evs8SgoKDDYrrCwUGjUqJHeeSAI5b9fBwcH4eeff9ZbPmrUKAGA3uvz+PHjBQDCjRs3DPZvzKZNmwQAwubNm2u0PRHVHKdMmNFPP/2EKVOm4JlnnsGgQYPwwQcfYOfOncjNzcUbb7yht21RUVGl83+1czXFpCI8KCQkBIMGDdJb1q1bNwDlo7MPGjx4sN6oqoODA6ZOnQqg/GtGU9NOR/j6669RXFxskn1qj5e5juu8efOwfft29OvXD0OHDtUt1361vH//ft2omlzaYz5jxgy9C9kCAgLw6quv4vbt20hLS9N7jLe3N8aNG6e37Omnn0bjxo2xY8cOaDQak9T2oHbt2qFdu3Z6y+Li4iAIAl5//XW9aTLx8fEA9M/Bzz77DIIg4KWXXsJff/2l9ycxMREajQZ79+41S+011aVLF6Snp+umCKSlpaF58+YYNGgQrl69ijNnzuiWq1QqdO7cGQCQk5OD77//Ht26dUP79u319jlx4kR4enoa/f81duzYKucM79u3Dx06dICfnx+OHTtmcNGVlGOqVqsxcuRIg+fy9fXF1atXcfDgwRocKUM5OTnw8/OT9Fig/FhU/D/t6emJdu3aGX0dA4DJkycbLBN7PCrOdS4sLMStW7dQVFSEzp07Iz09XTclTvv77dGjB1q3bq33nDNmzDCoQ/u6t23bNty/f7/af7v2uGVnZ1e7LRGJw4a4lvXs2ROPP/440tLScPfuXd1yDw8PlJSUGH2MdrsHv0YV48E5jMA/L67GYt1iYmIqXfbgvGNTGDhwIHr06IEFCxagbt26iIuLw/Tp043G09WU9njV9Ljm5ubixo0ben/KysqMPvb999/HtGnT0KlTJ3z22Wd6TV54eDhmzZqF7777DiEhIWjRogVeffXVKuf6VufChQsAgGbNmhms0y57cG5wVFSU0Q8DMTExuHPnDnJyciTXUxVj51rdunWNrtMur3gOZmRkAABatGiBgIAAvT/du3cHANy8edMstddU165dAUD3ISQtLQ1du3ZFXFwcXFxcdM3U3r170axZMwQEBACo+vfo4eGBqKgoo3O8H3744UpruXnzJnr06IHg4GAcOnQIISEhBttIOaZRUVFGU0Tmz58PT09PdOrUCUFBQXj22WexZs0a5OXlVVrjgwQZc2Arey0z9joWEBCgO8cqEns8Ll68iCFDhsDPzw9eXl7w9/dHQEAA1q5dCwD4+++/Afzzf9DY62f9+vV1H5a1xo4dizZt2mDcuHGoW7cuunXrhnfffReZmZlG/+3a42bJSUJE1opziBUQGRmJH374Abm5ubo3rwYNGuDcuXMoKSkxaGK0F4E0aNBA8nNWFY8l582pshfmBy++q46Liwt2796NX375BampqTh8+DDee+89zJs3D4sXLza4KK4m1Gq1wUU0FV25cgU+Pj66K+efeeYZg1GvzMxMg/ney5Ytw4QJE9ClSxf8+9//NvpBZfbs2Rg+fDh2796N77//Htu3b8eqVavQt29f7Nixw6bf0Ko61ypbV/Ec1I5c79q1q9LRfWNNUW2Kj4+Hk5MT9u7di9atW+Pq1au6i6jatm2LvXv3on///khPT8f48eNlP19VH4bVajUee+wx7Ny5E+vXrzf49gmQdkwre87HH38c58+fx969e7F//34cPHgQX375JWbOnIlDhw5VGz8YEBCg+2AghZiov8r+DWKOR0FBAeLi4pCXl4fXX38dzZs3h4+PDxwcHPDxxx9jy5Ytkr9tUavV+OGHH3D06FHs3bsX33//PZKTk5GcnIxNmzbpzU0G/vngGBgYKOn5iKhybIgVcO7cOTg7O+t9bRgbG4szZ87ghx9+QFxcnN72//vf/xAVFSX5gjop0tPTK1320EMP6Zap1WocP37cYFupb3itWrVCq1atAJSPujzxxBN4++23MW7cOLi4uIjal0qlQps2bXDo0CFkZWXpTQEpLi7GyZMn8cQTT+iWLV26VDfSoxUUFKT388KFCzFlyhT06NEDO3bsqDJ6LDw8HKNHj8bo0aNRWlqKYcOG4bPPPsPBgwdF360qKioKAHD69Gk8/vjjeuu0o+jabbT+/PNPox+w0tPT4ePjoxu1rIxSTfvDDz+MPXv2IDg4WHcuWBpvb2/ExsYiLS0NrVu3houLi+4CqC5dumDZsmVITU0F8M9oMvBPk3X69GmDfRYXF+PChQt6/79qwtnZGV9++SWGDBmC8ePHo7CwENOmTdPbxtTH1MPDA4mJiUhMTARQnpTQs2dPLFiwABs3bqzysU2bNsXBgwdx+fJlg4sDa+ucE3M89u3bh8uXL2P9+vUYMWKE3rp169bp/az9P2js9fPq1atGR9EdHBzQoUMHdOjQAUD5xYytWrXC5MmTDRriP/74A4DxbxiISB5OmTCTyu4ut2XLFvzyyy+6WCQt7VXpS5cu1dv+q6++0n1dV5s2b96MrKws3c8ajQbz588HUD6SqhUdHY38/Hz8+OOPeo9fvHix0f16eXkhNzfXYPlff/1lsKxu3bpo2LAh7t27V+Pbuz6osuO6evVqFBcX6x3X1q1bo2vXrnp/Kja88+bNw5QpU9C7d298/fXXlTbDeXl5BvMBnZyc0KJFCwCVnxtV0R7zefPm6Y1G/fXXX/jggw/g6+urSz/Qys/Px4oVK/SW7dixAxkZGejXr1+10WPaOavGfl/mpP2dTJ061ei8yry8vEqnwdSmrl274sqVK1izZg3atm2rm2fatWtX5OXlYfHixXB2dtb7gBsQEICOHTsiNTXV4P/M0qVLUVBQgP79+4uuxcnJCZ999hmGDx+O6dOnGySZmPKYGptqo50vW5NzW/th8OjRowbrauucE3M8tCPSD36T9ttvvxlEQgYEBKBDhw7Ys2cPfvnlF711c+fONXgeY8cyNDQU9erVM3os//e//8Hf399gjviff/6pm7dORNJwhNhM5s6diyNHjqBz584ICwvDvXv3cOTIEWzfvh3BwcFYvny53vZdu3bFoEGDsGXLFvTp0wd9+/ZFZmYm3nvvPcTExEiaMiBH48aN8fjjj2PMmDFQq9X4+uuvsW/fPgwcOFAvymnUqFFYunQp+vXrh9dffx0eHh745ptvKp1PqP06eeHChQgLC4NKpcLAgQMxd+5c7NmzB71790ZkZCScnJxw8OBB/Pe//0Xv3r31RtO12aI1meoxfPhwfPrpp1ixYgXy8vJ0d6pbtWoVOnXqVKObpgDABx98gGnTpqFevXp45plnsG3bNr31Xl5eumi4/fv3Y+TIkXj66acRHR0NX19fpKenY82aNahfv77eiGFNde7cGUOGDMGmTZuQkJCAp59+Whe7lp2djU8//dTgoquoqCjMmzdPN6qckZGB1atXIyAgwOib84NiYmLg7e2NVatWwcPDA76+vggMDNRdIGYubdq0wdy5czF9+nQ0bdoUgwYNQoMGDZCdnY1Tp05h586dSE9P101l2bhxI4YPH45Zs2YZZNYa85///Ae//vorgH/yo1NSUnRTZ8aNG2cw19OYLl264J133kF6ejreeecd3fLY2Fj4+PggPT0d7du3N/i9pKSkIC4uDp07d8aYMWN0sWuff/45WrRoYZBFXlMODg5Yv349PDw8MH/+fBQWFmL58uW6b0rEHNOqaF8bYmNj0aBBA+Tm5uKTTz4BAL2LSyvTo0cP+Pj4YNeuXQYjoNootsmTJ+OFF16Am5sbmjZtavI7s4k5Hu3bt0dwcDAmTJiACxcuICIiAhkZGVi3bh2aNWtm8A3Ze++9h7i4OHTq1AmvvvqqLnbtxIkTuig5raSkJFy6dAndu3dHREQESktLsWvXLpw+fRpjx47V2zYvLw+HDx/W5YJX1KVLlxq/JhJRJRRKt7B5O3fuFHr06CE0aNBAcHNzE1xdXYXo6GjhzTffFG7evGn0Mffu3RPmzZsnNGrUSHBxcRGCgoKEpKQkIScnp8bPW1ns2oPLBMF4vFfFqK0PPvhAiI6OFlxcXITQ0FBhxowZwr179wz2k5qaKrRu3VpwcXERAgIChNGjRwu3b982Gst17tw5oVu3boK3t7cAQNCegvv37xeef/55ISIiQnB3dxd8fHyE5s2bCwsXLhSKior09uHn5yeEhITU+Jjk5+cLkyZNEsLCwgRnZ2chLCxMeOutt4xGKVVGG89V2Z+K0XMXLlwQRo8eLcTExAg+Pj6Cu7u78NBDDwnjxo2rUbyXsd+LIJRH3y1fvlxo1qyZ4OrqKnh5eQkJCQl6sXla2t/5yZMnhW7dugleXl6Ct7e30LdvX+GPP/6o8b/7m2++EVq2bCm4uroaREYZ+/0aWyYIVcdpVfaYPXv2CE899ZTg5+cnODs7CyEhIUJCQoKwdOlSobi4WLddSkqKAED48MMPa/Rvqu53aaxGY+7duyd4enoKAAxi5vr06SMAEGbOnGn0senp6cJzzz0n+Pv7C87OzkJ4eLjw5ptvCrdv39bbThs1VjHqsKLKYg/feustAYDw8ssvC2VlZbrlNT2mlb1mCEJ5XGN8fLwQGBgoODs7C0FBQUKPHj2Eb7/91uj2xowbN07w8PAQ7ty5Y7Bu4cKFQmRkpODk5KT3/6CqY6H9nVZUVSSkVk2Px6lTp4SnnnpKqFu3ruDh4SG0bdtW2LlzZ6Xn9Y8//igkJCQIHh4eQp06dYRnnnlGyMzMNDiu27dvF/r27SuEhoYKrq6uQt26dYXY2FhhzZo1er83QRCEDz/8UABgEKknCP/E5BGRdCpB4EdK+seBAweQkJCADRs2GNyFzBKcPHkSLVu2xMcff6x3swNbcv78eTRq1Ahz5szB9OnTlS7H4vXr1w+nT59Geno6nJ2dlS6HauDKlSuIjo7G7NmzMWnSJKXLsXgajQbNmjVDTEyMwbdTRGQanENMVmXPnj1o0aJFjb6atVbXrl0DwCvJa+L+/fvYt28fFixYwGbYijRo0ACTJ0/GokWLJF8fYE8+++wz/Pnnn5Vem0FE8nGEmPRY+gixLfv777/x5ZdfYt26dThx4gTOnTuHyMhIpcsiIiKyeRwhJrIQWVlZGDt2LIqLi7Ft2zY2w0RERLWEI8REREREZNc4QkxEREREdo0NMRERERHZNTbERERERGTX2BATERERkV1jQ0xEREREds1J6QLMoaioCGfOnMEjjzwCDw8PpcshIiKiGrp9+zaKiopMsi8PDw/4+vqaZF9k22yyIT5z5gxat26N48ePo1WrVibbryAIyM/Ph7e3N1Qqlcn2ay8EQYBGo4GDgwOPnwQ8/+Th+ScPzz/5eA5W7/bt21i5ciVKS0tNsj8nJyeMHTuWTTFVyyYbYnMRBAEFBQXw8vLii5lE2jcDEo/nn3w8/6Tj+WcaPAerVlRUhNLSUrRs2RJeXl6y9lVQUIATJ06gqKiIDTFViw0xERERWRQvLy82sVSr+DGViIiIiOwaG2IiIiIismtsiImIiIjIrrEhJiIiIiK7xoaYiIiIiOwaG2IiIiIismtsiImIiIjIrrEhJiIiIiK7xoaYiIiIiOwaG2IiIiIismuK37p5+fLlOHToEJyc/inlgw8+QEBAAAAgJycHK1asQEZGBurUqYMXX3wRcXFxSpVLRERERDZG8YYYAPr27YuhQ4caXbdkyRJERERg2rRpOHfuHObOnYvw8HCEh4fXcpVEREREZIssoiGuzLVr13Du3DnMmDEDrq6uaNasGWJjY7Fv3z4MHz5ckZru37+Pe/fuwcGBs03EEgQBpaWl0Gg0UKlUSpdjdTQaDc8/GXj+yVPT8y/zUlml6yLDHOHi4mKO8oiIZLGIhjg1NRWpqanw9/dHnz590K1bNwBAVlYWAgIC4OXlpds2MjISv/32m8E+rl+/juvXrwMAMjIyzFbr7du34eTkxDdUCQRBQFlZGRwdHXn8JBAEgeefDDz/5Knp+TdrYVGl65YleyAkJMQc5RERyaJ4Q9ynTx+MGDECnp6eOH36NBYuXAhPT0888cQTuHv3rl4zDACenp4oLi422M/atWuRnJxcW2UTERERkY1QvCGOiorS/b158+bo1asXjhw5gieeeAJubm4oLCzU276oqAju7u4G+xk1ahQSExMBlI8QDx482Cz1+vr6ws/Pj19ZS6D9ypojnNJoNBqUlpby/JOI5588NT3/kidXPmXC39/RHKUREcmmeEP8IJVKBUEQAADh4eHIyclBQUGBbqT4woULRi+oCw4ORnBwsNnrc3Z2houLCxsSCQRBgIODAxsSiTQaDc8/GXj+yVPT8y/6oVosiojIRBR/Vz18+DCKioqg0WiQnp6Ob775Bm3btgUAhISE4KGHHsLmzZtRUlKC33//HT/++CM6d+6scNVEREREZCsUHyHetWsXPvjgA2g0Gvj7+2Pw4MF6OcOTJk1CSkoKXnjhBfj6+uKVV15h5BoRERERmYziDfGCBQuqXB8QEIA5c+bUUjXVY+yVdIy9koexa/Lw/JNHo9Eg81IZ8gruwsHBfMcvMqzqecaMbSMic1C8IbY2jL2SjrFX8jB2TR6ef/IIgoAV60sAXDPr8yxL9qhyPWPbiMgcOMxERERERHaNI8QiMXZNOsZeycPYNXl4/smj0Wgw7qUcqNV+Zp0ywWg2IlICG2KRGHslHWOv5GHsmjw8/+TRaDSIDHNEUJAbzz8isjl8VSMiIiIiu8aGmIiIiIjsGqdMiMTYK+kYeyUPY9fk4flXvcxLld92WaMRkJtr/ti12lJZvBtj3YjsExtikRh7JR1jr+Rh7Jo8PP+qN2thUQ22Mm/sWm2pLN6NsW5E9onDTERERERk1zhCLBJj16Rj7JU8jF2Th+df9ZInVzdl4pbZY9dqC+PdiKgiNsQiMfZKOsZeycPYNXl4/lUv+qHK12k0Gty4wdg1IrJNfFUjIiIiIrvGhpiIiIiI7BqnTIjE2CvpGHslD2PX5OH5V3WsWnVsLXbtQdoYNsauEdk4cqyaAAAgAElEQVQnNsQiMfZKOsZeycPYNXl4/tU0Vq06thG79iBtDBtj14jsE4eZiIiIiMiucYRYJMauScfYK3kYuyYPz7+qY9WqY2uxaw9iDBuRfWNDLBJjr6Rj7JU8jF2Th+df1bFq1WHsGhHZMr6qEREREZFdY0NMRERERHaNUyZEYuyVdIy9koexa/LYw/knJ1atOrYeu1YbrDXpRBtJVxHj6cjWsCEWibFX0lnrm4GlYOyaPPZw/pkmVq06thm7RpXTRtJVxHg6sjUcZiIiIiIiu8YRYpEYuyYdY6/kYeyaPPZw/smJVauOrceu1QZr/ZaCkXRkD9gQi8TYK+kYeyUPY9fksYfzT06sWnUYuyafPXwoI7JWfFUjIiIiIrvGEWKReJW/dPZwlb85MWVCHms4/8yZEiEXUybkq8mUicgwRyY4ECmADbFIvMpfOmudP2cpmDIhjzWcf7WTEiEXUybMaVmyBxMciBTAYSYiIiIismscIRaJKRPS8YISeZgyIY81nH/mTImQiykT8tXkWwomOhApgw2xSLzKXzp7uMrfnJgyIY81nH/mTImQiykT8lnDhzIie8VXNSIiIiKya2yIiYiIiMiuccqESIy9ks4aYq8sGWPX5LGG84+xa9aPsWlE1okNsUiMvZLOGmKvLBlj1+SxhvOPsWvWj7FpRNaJw0xEREREZNc4QiwSY9ek4xXW8jB2TR5rOP8Yu2b9GJtGZJ3YEIvE2CvprCH2ypIxdk0eazj/GLtGRKQMvqoRERERkV1jQ0xEREREdo1TJkRi7JV01hB7ZckYuyaPJZx/FWPVIsMM55oyrouISBlsiEVi7JV01hB7ZckYuyaPJZx/FWPVliV7GKxnXBcRkTI4zEREREREdo0jxCIxdk06a4i9smSMXZPHEs6/irFqjOciIrIcbIhFYuyVdNYQe2XJGLsmjyWcf5Ycq0ZEZM/4rkpEREREdo0NMRERERHZNU6ZEImxV9JZQuyVNWPsmjzmPv8qRqrZovJbN5chr+CuTd26+cH4O0bfEdknNsQiMfZKOkuIvbJmjF2Tx9znX8VINdt2TekCTOrB+DtG3xHZJw4zEREREZFd4wixSIxdk84SYq+sGWPX5DH3+VcxUs0WlU+ZuAW12s+mpkww/o6IADbEojH2SjpLiL2yZoxdk8fc55+tR6ppNBrcuOGIoCA3nn9EZHP4qkZEREREdo0NMRERERHZNU6ZEImxV9Ixdk0exq7JY4uxa4wMIyIyDTbEIjH2SjrGrsnD2DV5bDF2jZFhRESmwWEmIiIiIrJrHCEWibFr0jF2TR7Grslji7FrjAwjIjINi2qI79y5gzFjxiA4OBhLliwBAGRlZWHFihW4ePEi6tWrh6SkJLRo0UKxGhl7JR1j1+Rh7Jo8jF0jIqLKWNS76oYNGxAaGqr7ubS0FHPmzEFsbCy2bNmCgQMHYv78+bh9+7aCVRIRERGRLbGYhvj333/HtWvX0LVrV92yU6dOoaSkBAMGDICzszM6duyIsLAwHDlyRMFKiYiIiMiWWMSUifv372Pt2rV48803ceHCBd3yS5cuISIiQu/r4YYNGyIrK0uJMgEwdk0Oxq7Jw9g1eeSef9pYtQejzrQYeUZEZL0soiHevn07WrRogcjISL2GuLi4GJ6ennrbenp6Ijs722Af169fx/Xr1wEAGRkZZquVsVfSMXZNHsauySP3/NPGqj0YdabFyDMiIuuleEN87do1pKWl4f333zdY5+7ujsLCQr1lhYWFcHd3N9h27dq1SE5ONludRERERGSbFG+IMzIy8Pfff2P06NEAgHv37uHevXt48cUX8corryArKwsajUb3FXFmZibi4uIM9jNq1CgkJibq9jl48GCz1MvYNekYuyYPY9fkkXv+aWPVGHVGRGR7FG+IO3TogFatWul+/v7777F//37MnDkT3t7ecHFxwVdffYW+ffvihx9+QFZWFtq3b2+wn+DgYAQHB5u9XsZeScfYNXkYuyaP3POPsWpERLZL8YbY1dUVrq6uup89PT3h6OiIunXrAgCmT5+OlStXYuvWrQgMDMTUqVPh6+urVLlEREREZGMUb4gf1KVLF3Tp0kX3c0REhO4mHUREREREpmZxDbGlY+yVdIxdk4exa9JlXipjyolMGo2A3Nwy5BXchYODssevsug7gPF3RCQNG2KRGHslHRsSeRi7Jp02Mo1M4ZrSBVQafQcw/o6IpOEwExERERHZNY4Qi8TYNekYuyYPY9ekS57MKRNylU+ZuAW12k/xKROMviMiU2NDLBJjr6Rj7Jo8jF2TLvohfiCTS6PR4MYNRwQFufH8IyKbw1c1IiIiIrJrHCEWiVf5S8eUCXmYMlG5zEtl1W5TG1Mmqko/AJiAQERkqdgQi8Sr/KXjHE55mDJROUtJkagq/QBgAgIRkaXiMBMRERER2TWOEIvElAnpeFGTPEyZqFzyZMuYMsH0AyIi68SGWCRe5S8dUybkYcpE5aIfqn4bfiAjIqLK8F2ViIiIiOwaG2IiIiIismucMiESY6+kY+yaPIxdq5ylxK7ZmooxchqNRsFKiIjMiw2xSIy9ko4NiTyMXaucpcSu2ZqKMXKCIPC8IyKbxWEmIiIiIrJrHCEWibFr0vEqf3kYu1Y5S4ldszUVY+Q0Gg1yc3MVrIaIyHzYEIvE2CvpGLsmD2PXKsfYNfPjHGIismV8VyUiIiIiu8aGmIiIiIjsGqdMiMTYK+kYuyaPPceu1SRWrTqcQyyPRiMgN7cMeQV34eBg28evYtycMS4uLrVUCRHVFjbEIjH2Sjo2JPLYc+waY9UsyTWlCzC7inFzxoSEhNRSJURUW+xrmImIiIiI6AEcIRaJsWvS8Sp/eew5dq0msWrV4TcU8pRPmbgFtdrP5qdMVIybIyL7wIZYJMZeScfYNXnsOXatJrFq1eEHMnk0Gg1u3HBEUJCb3Z1/RGT7+KpGRERERHaNDTERERER2TVOmRDJXmOvTIGxa/JYa+yaKSLTTMGS5xBrY74Y50VEpAw2xCLZa+yVKVhyQ2INrDV2jZFp1dPGfDHOi4hIGdYzzEREREREZAYcIRaJsWvS8Sp/eaw1ds0UkWmmYMnfUDDmi4hIWWyIRbLX2CtTYOyaPNYau2aKyDRT4AcyIiKqjPW8qxIRERERmQEbYiIiIiKya5wyIZI1xl5ZCsauyWOpsWumjlXTRpBVxDgyIiIyJzbEIllj7JWlsOSLmqyBpcaumTpWTRtBVhHjyIiIyJwsZ5iJiIiIiEgBHCEWibFr0vEqf3ksNXbN1LFqjCAjIqLaxoZYJGuMvbIUjF2Tx1Jj1ywlVo2IiEgqy3lXJSIiIiJSABtiIiIiIrJrnDIhkiXGXlkLxq7Jo1TsmphYNUamERGRNWJDLJIlxl5ZC8auyaNU7JqYWDVGphERkTXiMCcRERER2TWOEIvE2DXpGLsmj1Kxa2Ji1RiZRkRE1ogNsUiWGHtlLRi7Jo9SsWuMVSMiIlvHro6IiIiI7BobYiIiIiKya5wyIRJj16Rj7Jo8UmLXxESm2Tp7SzlhBB4RUc2xIRaJsWvS2VtDYmpSYtfERKaRbWEEHhFRzXGYk4iIiIjsGkeIRWLsmnSMXZNHSuyamMg0W2dv31AwAo+IqObYEIvE2DXpGLsmj5TYNUam/YMfyIiIqDJsiImIiMhqlJWV4cyZM8jNzYVarcYjjzwCR0d+I0LysCEWiSkT0jFlQp7aSJlgMgERWbLMzEy8++67uHfvHvz8/HDr1i24urri7bffRmRkpNLlkRVjQywSUyaks7c5nKZWGykTTCYgIku2YsUK9OzZE/3799ct2759O1auXImlS5cqWBlZOw5zEhERkVW4evUq+vXrp7esX79+uHr1qkIVka3gCLFITJmQjhc1yVMbKRNMJiAiS9a0aVOcOnUKjz76qG7Zb7/9hiZNmihYFdkCNsQiMWVCOqZMyMOUCSKyR5988onu735+fnj33XfRqlUrBAQEIDs7GydOnEBCQoKCFZItsIiGeOXKlfj5559RXFwMb29vdO/eHc899xwAICsrCytWrMDFixdRr149JCUloUWLFgpXTERERLXh9u3bej936NABAFBYWAhPT0906NAB9+/fV6I0siEW0RAnJiZi5MiRcHV1RU5ODmbPno2QkBC0bdsWc+bMQffu3TF//nwcO3YM8+fPx5o1a+Dr66t02URERGRmr7/+utIlkB2wiIY4LCxM72eVSoVr167h1KlTKCkpwYABA+Dg4ICOHTviP//5D44cOYJevXopUitj16Rj7Jo8xmLXxMaq2TOmnMij0QjIzS1DXsFdREVU/tbBmD4yp+zs7ErXBQYGAgBycnIQEBBQWyWRjbCIhhgonyO0a9culJSUIDAwEAkJCTh69CgiIiL0ms+GDRsiKyvL4PHXr1/H9evXAQAZGRlmq5Oxa9KxIZHHWOya2Fg1IvmuGY3n02JMH5lTUlISBEEweA8RBAE7d+4EAIwdOxb/+te/lCiPrJjFNMRDhw7Fiy++iPPnz+PYsWPw9PREcXExPD099bbz9PQ0+glx7dq1SE5Orq1yiYiIqJZt27at2m0+++yzWqiEbI3FNMRA+VSJRo0a4fjx49iyZQv8/f1RWFiot01hYSHc3d0NHjtq1CgkJiYCKB8hHjx4sFlqZOyadIxdk8dY7JrYWDV7xm8o5CmfMnELarUf/P0t6q2D7IizszOA8mkR2ls3Pzg9wsmJ5yeJZ5FnjUajwfXr19GqVSts374dGo3mnzmTmZmIi4szeExwcDCCg4PNXhtj16Rj7Jo8xmLXGKtWc/xAJo9Go8GNG44ICnLj6x8pJicnB0uWLMHZs2fh6emJwsJCREdHY+LEiZw3TLIo/qpWUFCA/fv3o6ioCBqNBunp6di9ezceffRRNGvWDC4uLvjqq69w//59HD58GFlZWWjfvr3SZRMREVEtW758OaKiorBlyxZ89tln2LJlCxo2bIiUlBSlSyMrZxEjxHv37sWHH34IjUYDtVqNfv36oVevXlCpVJg+fTpWrlyJrVu3IjAwEFOnTmXkGhERkR36888/MXv2bN3UCXd3d7z00ktmmyZJ9kPxhtjLywvvvvtupesjIiKwZMmSWqyoaoxdk46xa/Iwdk0eU84hjgwzvMU148aIzC8iIgKXLl1CVFSUbllWVhYiIiKUK4psguINsbVh7Jp0vKhJHsauWQ5jsWOMGyMyvyZNmiA5ORnx8fEICAhATk4ODhw4gG7dumHPnj267Xr06KFglWSN2BATERGRVThz5gxCQ0Nx4cIFXLhwAUD5zb3Onj2Ls2fP6rZjQ0xisSEWibFr0vEqf3kYuyaPKb+h8Pc3nDJBROZX1RRLIjnYEIvE2DXpGLsmD2PX5OEHMiIiqgy7OiIiIrIKxu5IO2fOHAUqIVtToxHiyMhIUSMq2nk9RERERKbSpEkTg2UxMTEKVEK2pkYNcd++ffUa4i+//BJ37txB165dUa9ePdy8eRN79+5FnTp1MGDAALMVawkYuyYdY9fEqxirVn7r3DLkFdyFgwOPn1hMOSlnLDJOi9FxZOmM9Rj9+/dXoBKyNTVqiJcvX677++LFixEaGoo9e/bAx8dHtzwvLw89e/ZEvXr1TF+lBWHsmnRsSMQzHqt2rdbrINthLDJOi9FxRLUjIiICvXv3xsqVKyvd5vbt26hbty42bNiAYcOG1V5xdkr0MGdKSgqmTp2q1wwDQJ06dTBlyhSsWLHCZMURERER2ZodO3Zg4sSJSpdBFYhOmcjNzUVeXp7RdXl5efj7779lF2XJGLsmHa/yF69irFr5lIlbUKv9OGVCAn5DUY6RcUTKa9mypdIl0ANEN8RdunTB5MmTERoaivj4eN3yAwcOYMqUKejSpYtJC7Q0jF2TjrFr4lWMVdNoNLhxwxFBQW48/yTgBzIiqi3r1q3Du+++i+zsbLRr1w4LFy7EY489ppv+YGzKhLHHUO0R/a66du1ahISEoHPnzlCr1YiOjoZarUaXLl0QHByMNWvWmKNOIiIisnP79u1DUZHxW9b/8ccfuHZN+Wssdu3ahaSkJCQkJGDHjh3o0qULnn32WZM/hkxL9AhxcHAwfvrpJ+zZswc//vgjrl+/juDgYMTGxvJWiURERGQ2KSkp2L17N5KTk+HhoX+BaGZmJn7++We8/fbbClVXbu7cuejYsSM2bNgAAHjyySdx9+7dKvOSpTyGTEvynep69Ohhlw0wY9ekY+yavoqRasZEhjkyBouIqAJXV1eEhYVh1qxZmD17Njw9PXXr2rVrh82bNytYHVBWVobjx49j0aJFessHDBhQaXMr5TFkejVqiHNzc+Hr6wsHBwfk5uZWu71arZZdmKVi7Jp0vKhJn/FItX8sS/ZgDBYR0QPGjRuHNWvWYMaMGZg9e7Yu9crLywulpaWK1paTk4PS0lIEBgbqLa8qklbKY8j0ajTMGRAQgJ9//hkA4O/vj4CAgCr/EBEREZnL6NGj0aRJE0yePBl//PEHAOCbb75BZGSkonUFBATAyckJ2dnZestv3rxp0seQ6dVohPjjjz9GVFSU7u/2PLrH2DXpeJW/voqRasYwHouIqHIvvfQS1Go1pk6dCpVKBTc3N8yaNUvRmhwdHdGqVSvs2LED48eP1y3/8ssvTfoYMr0aNcRDhw7V/d3e75bC2DXpGLumr2KkGhERVe/Bhvfpp5/Gk08+ievXr6NBgwZwdXVVqLJ/TJs2DX379sXw4cMxcOBAHD9+HJs2bTL5Y8i02NURERGRVYiJiTFY5uHhgaioKItohgEgMTERa9asQVpaGvr164dvv/0W//rXv0z+GDItySkTRERERLXp0KFDCAoKwsMPPwwAuHv3Lu7cuaO3zYMXpylh1KhRGDVqlO7n27dv662/ePFitY8Byr9ZpdrBhlgkxq5JZ2+xa9XFqolVfuvmMuQV3FX81s2RYf/Mb2Y0HBHVls2bN2PmzJm6n69evYoJEyZAEASoVCoIgoCdO3cqWCFZKzbEIjF2TTp7i12rLlZNOuXvxLQs+Z9AfEbDEVFtycvLQ/369XU/R0ZGQq1WY+3atVCpVHjhhRcUrI6sGRtiIiIisgru7u4oLCyEl5cXAKCwsBCCIMDZ2VnhyoDs7GyD6RsVaePhzp8/L2q/fn5+qFu3rqzaqHqSG+Jz587p3br5scceQ3R0tClrs0iMXZPO3mLXqotVE6t8ysQtqNV+ik+ZYCQcESmhcePG2Lhxo26u7caNG9GkSROFqypXUFCAvLw8k++34t34yHxEN8QFBQVISkrCF198AY1GAzc3N9y9excODg549tlnsW7dOt0nN1vE2DXp7C12zdSxahqNBjduOCIoyI3nHxHZpeHDh2POnDkYOHAgBEFAaGgoZsyYoVvfqVMn5Yr7/7QX/JnCuXPnTLYvqprohnjcuHHYtWsX1q1bhwEDBsDb2xv5+fnYtm0b3njjDYwbNw4bNmwwR61ERERkxwIDA5GSkoKrV69CpVIhJCREb4BlzJgxClZH1kx0Q7x9+3YsXLgQw4cP1y3z9vbGiBEjcPfuXUydOpUNMREREZmFSqVCgwYNlC6DbIzohtjNza3Se4U3bNjQIia2mxNj16Sztdg1U8eqVceSYtesUXUpJxWj5IxhvByR8nbu3ImGDRuiWbNmAMqTn65cuaK3TdOmTZUojayc6IZ4+PDhWL16NZ588km9NxVBELBq1Sq9kWNbxNg16Wwtds18sWrVUT52zRZVjJIzhvFyRMrbuXMnFixYoPs5Pz8fM2fOhI+PD4Dy9+ivv/5aqfJsxocffohZs2YhPz8fv/32Gxo2bKh0SWZXo2HOZcuW6f74+fnh+PHjaNSoEcaPH4/58+dj/PjxaNSoEU6cOGERd4ghIiIi21NQUKDXZ4SGhsLHxwcbN27Exo0bLeb2zeZWUlKCl19+GZGRkfD29kaTJk3w+eef69ZHRETA3d0dXl5e8PLyMkjiUKlU8PT01K3v2bOnbt39+/fxxhtv4N///jcKCgr0muGzZ8/Czc0NAwcO1C07duwYnnzySfj5+cHPzw+9evXSRcwB5YNhM2bMQIMGDeDj44PHH38cR48e1a3fv38/EhISUKdOHQQFBZn0OIlRoxHiiRMnGl3+/vvvGyybMmUKJk2aJK8qC8bYNelsLXbN1LFq1bGk2DVrVN03FIySI7J8Xl5e+Pvvv3W5vLdu3YKTk/3dUqG0tBQhISFIS0tDZGQkjhw5gl69eiEyMhLt2rUDAOzYsQM9evSodB/Hjx/HI488YrD85s2bKC4u1k1LqWjMmDGIjY3VW/b3339jxIgR+OKLL+Du7o4ZM2YgMTERGRkZAIAtW7bgo48+wqFDhxAVFYVVq1YhMTERN27cgJOTEzw9PTFixAgMHjwY06ZNk3NYZKnRWaTRaMxdh9Vg7Jp0tha7ZupYteowdk0eW/tARmSPWrVqhVWrVmHkyJEQBAFr165Fq1atlC4LALAzVYMffqkD4KYJ91oH771juNTT0xPvvPPPig4dOqB9+/Y4evSoriGWIiMjA23atAEA+Pv7Izo6GsePHwcAfPLJJ6hXrx6io6Nx5swZ3WMqji4DwIQJE7Bo0SLcunULfn5+yMzMRMeOHdGoUSMA5VNvx40bh+vXryM0NBSxsbGIjY3FgQMHJNdtCnxXJSIiIqvw4osvoqysDElJSRg1ahQcHBzw4osv6tY/++yzClannMLCQvz88896FxQOHToUAQEB6NSpE44cOWLwmM6dO6NevXro1asXTp8+DaD8xifav//111+6ZvjWrVt45513sGzZsmprOXjwIIKCguDn5wcAGDRoEP744w9kZGSgtLQU69atQ7NmzfRuwW0JJH3PUFhYiI0bN+Lw4cPIzc2FWq1Gx44dMXToUJu/owpTJqSz5ZQJYwkFTCUgIjItHx8fzJw5EyUlJVCpVAavswMGDFCoMuVoNBoMGzYMjz32GLp37w4A2Lx5M1q3bg2g/G5+PXv2xKlTpxAeHg4AOHDgANq1a4eSkhIsXLgQ3bt3R0ZGhu7ixAdNmjQJr732GoKDg6us5cKFCxg7dixSUlJ0y+rXr4+4uDg0adIEDg4OqFu3Lnbv3m1xfZTohvjy5cvo1KkTLl68iBYtWqBevXo4e/Ystm3bhmXLlmH//v0IDQ01R60WgSkT0tlyyoSxhAKmEhARmceDF8+lpqbiySefVKga5QiCgNGjR+PatWtITU3Vvbd26NBBt82YMWOwdetW7N69G6NHjwYAxMfHAygfuJk7dy42bdqEo0ePGp1z/P333+PEiRNYt25dlbVcvnwZXbt2xeTJk/H888/rlicnJ+Po0aPIzMxEgwYN8M033+Cpp57CyZMnLep9UnRD/OabbwIA0tPTER0drVt+9uxZ9O7dGxMmTMAXX3xhugqJiIiIAKSlpRldvm7dOri4uCAoKAiNGzeu5arK9X3SAXGxf5vh1s3Gv3kXBAGvvvoqTp48ib1798LLy6vS/Tg4OEAQBEnr09LScP78ed0Uh4KCApSVlSE6Ohpnz54FAFy5cgWdO3dGUlKSrk/U+u233/D888/rRqcTExMREBCAo0ePWtSIvuiG+LvvvsPatWv1mmEAiI6Oxpw5c3SfPmwVUyaks7WLmiqmTDChgIjI/FJTU40uLysrw+7du5GdnY02bdpg7NixtVxZ7Rs7diyOHTuGtLQ0vakOly5dQlZWFh5//HEA5RfD/fTTT/joo48AAKdPn0ZJSQmaN2+Oe/fuYdGiRSguLq70YryJEyfq9XZLlizB+fPn8eGHHwIArl27hoSEBAwePBhTpkwxePzjjz+Obdu2YdCgQQgJCcHu3btx4cIF3XxnjUaDe/fu4d69ewCAu3fvQqVS1XqEnuiGuLS0FO7u7kbXubu7o6ysdqOoahtTJqRjygQREcmxaNEio8uff/55LFq0CCUlJRgxYoTNN8RZWVlYtWoVXF1d9aapvv322+jXrx/GjRuH8+fPw8XFBTExMdi1axeioqIAANnZ2RgzZgwuX74Md3d3tGnTBqmpqfD19TX6XNqs4oo/u7m56fKg161bh/Pnz2Px4sVYvHixbrv09HSEhYXhrbfeQk5ODmJjY5Gfn4+wsDCsX79eF/l26NAhJCQk6B7n7u6O8PBwXLx40WTHqyZEN8Tt27fH3LlzER8fjzp16uiW5+Xl4d1330X79u1NWiARERFRVbQXk7m6uur1JrYqPDy8yikQJ0+erHRdQkKCXmzagyIiIqrc9+zZs/V+njVrFmbNmlXp9q6urkhJSdG70K6iTp06Vfl8tUV0Q7x06VLExcUhNDRUF9mRnZ2NtLQ0ODs74+OPPzZHnUREREQoKCjA/Pnz0bx5c/Tv3x9OTk546aWXdOtXrVqlYHVkrUQ3xE2bNsWvv/6K9957D4cPH8bp06ehVqsxcuRIjB8/Hg0aNDBHnRaDsWvSWVvsWsVYNUtQfqe6MuQV3LXbO9UZi7cDGHFHZE9KS0uRlZWF8PBwjB8/HqNGjdLL3yWSQlIOcWhoaI3CmW0RY9eks7bYtYqxapblmtIFKMZYvB3AiDsie+Po6IikpCRkZmZi9erVqF+/PkaMGAFvb2+lSyMrVaOGuHnz5vj888/RtGlTNGvWrMpmRqVSQa1WIzY2FpMnT4ZarTZZsURERERakZGRWLRoEVJTU/HWW29hwIAB6NKli9JlkRWqUUPcunVr3R3oWrduXe3oXn5+PtavX4+zZ8/i66+/ll+lBWHsmnTWFrtWMVbNEpRPmbgFtdrPbqdMMN6OyL5NmzYN9+/fR35+PqZNm6a3zsnJCSkpKYo3xOXZwWRtatQQb9iwQff3jRs31mjHO3fuxJAhQyQVZckYuyadtcWuWVqsmkajwY0bjggKcuP5R0R2qWPHjiguLsbly5fRsU/MatEAABofSURBVGNHpcvR4+/vrxs8NKWqbrhBpiNpDnFNxMfHY9OmTebaPREREdmZHj16oKioCJcvXzZ6m2El+fj46N0gg6yL2YaZfH190bdvX3PtnoiIiOyQh4cHXnvtNaXLIBtjthFiW8XYNeksLXbN0mLVjKkYM6bRaAzOP8aNEZE9mTZtGgYOHIhmzZoZrNuzZw9cXFzQuXNnBSoja8eGWCTGrklnabFrlhur9o+KMWOCIBicf4wbIyJ7kpGRgQULFuCtt95CixYt9NaFhobi448/ZkNMknCYk4iIiKyCs7MzJk6ciCVLlhjcnjg6OhrXrtlvTjvJwxFikRi7Jp2lxa5ZWqyaMRVjxjQaDUpLS3n+EZFda9myJSZPnoyFCxfi1VdfRdu2bQEAxcXFcHNzU7g6slZsiEVi7Jp0lha7ZmmxatXRaDQ8/4iIADRt2hRvv/025s6di5MnT6Jp06ZITU1FbGys0qWRleK7KhEREVmFwMBA3d8bN26MpUuXorCwEF988QXq16+P4cOHK1gdWTOOEBMREZFVWLFihd7PQUFBmDBhgkLVkC1hQywSY9ekY+yaPOW3bi5DXsFdu711c0UVI+kYP0dERHKwIRaJsWvSMXbNVHgVNaAfScf4OSL7kJOTg5SUFJw7dw7h4eGYPHkyzp8/j2+++QaBgYEYNmwYb3VMknCYk4iIiKzChx9+iODgYMybNw9hYWF4//33sXv3brRr1w7Z2dlYvXq10iWSleIIsUiMXZOOsWvylE+ZuAW12o9TJqAfSUdE9iEjIwPr16+Hq6srXn75ZTz//PPYvHkzvL29ER8fj1GjRildIlkpxRvi+/fvY82aNfj111+Rn58Pf39/PPfcc4iPjwcAZGVlYcWKFbh48SLq1auHpKQkg7vT1CbGXknH2DV5NBoNbtxwRFCQG88/IrJL2vcRAHB0dNS9pwDl78+CIChZHlkxxd9Vy8rKoFarMXfuXGzduhWvvvoqVq9ejTNnzqC0tBRz5sxBbGwstmzZgoEDB2L+/Pm4ffu20mUTERFRLYuIiMC2bdtw584dfPHFF4iMjMTKlSvx888/IyUlBTExMUqXSFZK8YbYzc0NL7zwAoKCgqBSqRATE4PGjRsjIyMDp06dQklJCQYMGABnZ2d07NgRYWFhOHLkiNJlExERUS0bMWIE9u7diyFDhuDkyZOYM2cOfH19sW7dOpSUlGD06NFKl0hWSvEpEw+6e/cuzp8/jz59+uDSpUuIiIjQ+3q4YcOGyMrKUqw+xq5Jx9g1eaqLXasYQ6bFODIisiVRUVH4+OOPkZ+fD29vbwDAyJEjMXLkSIUrI2tnUQ2xRqPB8uXL0ahRI7Rs2RLnzp2Dp6en3jaenp7Izs42eOz169dx/fp1AOWT7s2FsWvSMXbNVIzHrlWMIdNiHBkR2SJtM0xkKhYzzCkIAlatWoXc3FxMmjQJKpUK7u7uKCws1NuusLAQ7u7uBo9fu3YtWrdujdatW2Pw4MG1VTYRERHVki1btqCszPi3e8eOHcM333xTyxWRrbCIEWJBELBmzRpkZmZizpw5uoY3LCwM27dvh0aj0U1RyMzMRFxcnME+Ro0ahcTERADlI8TmaooZuyYdY9fkqS52jTFkRGTrtm7div79+8PR0fD1TqVSIS0tDb169VKgMrJ2FtEQr127FmfPnsXcuXPh4fHP177NmjWDi4sLvvrqK/Tt2xc//PADsrKy0L59e4N9BAcHIzg42Oy1MnZNOsauycPYNSKydyqVCl988YXRhjg/P1/Ra4zIuineEGdnZ+O///0vnJ2dMWLECN3yAQMG4LnnnsP06dOxcuVKbN26FYGBgZg6dSp8fX0VrJiIiIiUcu3atUoHBdq1a1fL1ZCtULwhDgwMxL///e9K10dERGDJkiW1WBERERFZqvHjx8PZ2VnpMsjGKN4QWxvGrklX27FrVcWqRYY5MpKMiMjKJCQk8P2XzIINsUiMXZOutmPXqopVW5bswUgyIiIr8/rrrytdAtkofswiIiIiIrvGEWKRGLsmXW3HrlUVq8aIMiIiItJiQywSY9ekq+3YNWuLVSMiIiJlsKsjIiIiIrvGhpiIiIiI7BqnTIjE2DXpxMSuVRWZZq/Kb91chryCu7pbN0eGVT0XmtFyRERE1WNDLBJj16QTE7tWVWQaXdP9bVmyRxXbgdFyRERENcBhTiIiIiKyaxwhFomxa9KJiV2rKjLNXpVPmbgFtdpPN2WC8XFERETysSEWibFr0omJXWNkmiGNRoMbNxwRFOTG84+IiMiE+K5KRERERHaNI8QiMWWiZoylRIi5qM6SaZMdmOBARERkG9gQi8SUiZqx5ZQIbbIDExyIiIhsA4c5iYiIiMiucYRYJKZM1IyxlAhbmTLBZAciIiLbwoZYJKZM1IyxlAgxsWtEREREtYVdHRERERHZNTbERERERGTXOGVCJMau1Ywtx64ppfxOdWXIK7iru1MdGaeNxtNiRB4REVWFDbFIjF2rGVuOXVPeNaULsHjaaDwtRuQREVFVOMxJRERERHaNI8QiMXatZmw5dk0p5VMmbkGt9uOUiWowGo+IiMRgQywSY9dqhrFrpqfRaHDjhiOCgtx4/hEREZkQ31WJiIiIyK6xISYiIiIiu8YpEyIxdq2csVi16phzDvGDMVsAo7aIiIioZtgQi8TYtXKWFqv2YMwWwKgtIiIiqhn7HuYkIiIiIrvHEWKRGLtWzlisWnXMOWWCMVtEREQkFRtikRi7Vs5YrFp1GLtGRERElsi+uzoiIiIisntsiImIiIjIrnHKhEiWELsmJfLMEljSrZsjwxwZy0ZEREQA2BCLZgmxa5YWeWaNliV7MJaNiIiIAHDKBBERERHZOY4Qi2QJsWtSIs8sgSVNmWBMGxEREWmxIRbJEmLXpESeWQLGrhEREZEl4pQJIiIiIrJrbIiJiIiIyK5xyoRItRG7po1ViwwzPs+VcWFEREREpsOGWKTaiF3TxqotS/Ywup5xYURERESmwykTRERERGTXOEIsUm3Ermlj1RgNRkRERGR+bIhFqo3YNWuNVSMiIiKyRpwyQURERER2jQ0xEREREdk1TpkQyRSxa9pYNWtXWSwcwGg4IiIish5siEUyReyaNlbN2lUWCwcwGo6IiIisB6dMEBEREZFd4wixSKaIXdPGqlk7xsIRERGRLWBDLJIpYtcYq0ZERERkOThlgoiIiIjsGhtiIqL/197dxlRd/38cfx1A4QBewNQzJgLaxT9cjoVbaaJSDbzhvCDJOcSmzsG6mtpqf1vpX9JwblbYT5SzbuDSJc7MZtYS82IpuelwS23MYgoOZYKihQrC4Zz/jcb5dQCF7wE5F9/n4xbnw9cPb91n+vbDm9cBAJgaIxMGEbvmPZfLpY6ODoWGhspisRDbBgAA/AINsUHErg0cYtsAAIA/YGQCAAAApsYNsUHErnmv68gEsW0AAMAf+EVDfOjQIR07dkw1NTWaOnWq3n//fffnamtr9Z///Ec1NTWy2WzKy8tTSkqKz2olds17LpdLDoej3yMnAAAAA8kvRiZiY2O1cOFCZWZmeqw7HA5t2LBBzz//vPbs2aNFixZp06ZNunPnjo8qBQAAQLDxixviF198UZJ0+fJlNTc3u9cvXLigBw8eKDs7WyEhIZo+fbq+//57VVRUaPbs2T6ptbeUCbMmSPRF15EJs+maqkGSBgAA/sEvGuKHuXr1qpKSkjyazwkTJqi2trbbs/X19aqvr5ckVVVVPbaaekuZIEECD9M1VYMkDQAA/INfN8QtLS2KioryWIuKilJDQ0O3Z+12uwoKCgarNAAAAAQJv26IrVar7t2757F27949Wa3Wbs/m5+dr7ty5kv65Ic7NzX0sNfWWMmHWBIm+MPvIBKkaAAD4J79uiBMSErR//345nU53A3rlyhXNmDGj27NxcXGKi4t77DX1ljJh1gSJviBlAgAA+CO/SJno6OhQW1ubnE6nnE6n2tra5HA4NGnSJA0dOlTffvut2tvbderUKdXW1mratGm+LhkAAABBwi9uiPfu3auysjL364qKCr388statWqVPvroI23btk1lZWUaM2aMPvjgA40cOdKH1QIAACCY+EVDnJOTo5ycnB4/l5SUpC1btgxyRQ9H7Jr3fDFD3DXq7N+IPQMAAJKfNMSBhNi1wNI16uzfiD0DAACSn8wQAwAAAL7CDbFBxK55zxcjE0SdAQCA3tAQG0TsmveIXQMAAP6IkQkAAACYGg0xAAAATI2RCYMGInbtUVFgEnFgAAAAg4mG2KCBiF17VBSYRBwYAADAYGJkAgAAAKbGDbFBAxG7RhQYAACA/6AhNojYNQAAgODCyAQAAABMjYYYAAAApsbIhEG9xa71BbFqAAAA/oOG2KDeYtf6glg1AAAA/8HIBAAAAEyNG2KDeotdAwAAQGChITaot9g1AAAABBa6OgAAAJgaDTEAAABMjZEJg3qLXbtytfe3bg5W4xP++5bURMsBAIBAQUNsUG+xa/+3+f4gV+Q/PiuIdH9MtBwAAAgUjEwAAADA1LghNqi32LWC/zXvyMSoUaG9PwQAAOBnaIgN6i127X+eHOSCAAAA0C+MTAAAAMDUaIgBAABgaoxMGGT22LXOaDVi1QAAQLCgITbI7LFrndFqxKoBAIBgwcgEAAAATI0bYoPMHrtGtBoAAAg2NMQGEbsGAAAQXBiZAAAAgKnREAMAAMDUGJkwyEjsWmdEWVdElgEAAPgPGmKDjMSudUaUdUVkGQAAgP9gZAIAAACmxg2xQUZi14goAwAA8H80xAYRuwYAABBcGJkAAACAqXFDbJCRlAl4crlc6ujoUGho6EN/KNEfdKaDkAYCAIA50BAbZCRlAoGpMx2ENBAAAMyBkQkAAACYGjfEBhlJmYCnQBmZIB0EAABzoSE2iJQJ77lcLjkcjkeOnAAAAAw2RiYAAABgajTEAAAAMDVGJgwids17gTJD3FVnDFtXxLIBABAcaIgNInbNfDpj2Loilg0AgODAyAQAAABMjRtig4hd816gjkwQwwYAQHCjITaI2DXvEbsGAAD8ESMTAAAAMDUaYgAAAJgaIxMGEbvmvUCdIfa1ztg3p9PZ7fwR/QYAQP/REBtE7BoGW2fsm8vl6nb+iH4DAKD/GJkAAACAqXFDbBCxa95jZMI7nbFvTqdTDofjkecPAAAYR0NsELFr3iN2rX+cTmev5w8AABgXEA3x3bt3VVxcrHPnzslqtSorK0vz5s3zdVkAAAAIAgHRENvtdrW3t6u0tFQNDQ1au3at4uPjNXnyZF+XBgAAgADn9993bW1tVUVFhZYsWaLIyEglJSUpMzNTR44c8XVpAAAACAJ+f0N87do1uVwuJSYmutfGjx+v06dPezxXX1+v+vp6SVJVVdWg1ggAAIDA5fcNcWtrqyIjIz3WoqKi1NLS4rFmt9tVUFAwmKUBAAAgCPj9yERERES35vf+/fuyWq0ea/n5+aqsrFRlZaV27949mCUCAAAggPn9DfHYsWMlSVevXlVCQoIk6cqVK+6PO8XFxSkuLm7Q6wMAAEBgC4gb4mnTpmnXrl26f/++amtrVV5eroyMDF+XBgAAgCDg9zfE0j/jENu2bdPSpUtltVq1YMECItcAAAAwIAKiIY6OjtaaNWt8XQYAAACCkN+PTAAAAACPEw0xAAAATI2GGAAAAKYWEDPERnXmFg/0O9Y5nU7dunVL169fV0gI/5cwyuVyqaOjQ6GhobJYLL4uJ+Bw/vqH89c/nL/+4wz2rrGxUfX19bp161a/97p79+4AVASzCMqGuKamRpKUm5vr20IAAIBXBuK9BcLCwrq92y3QE4vL5XL5uoiBdvPmTR0+fFhJSUnd3tGuP6qqqpSbm6vdu3crOTl5wPYF+oLzB1/i/GGwNDc3Kz4+fkD+/Y6MjNTIkSMHoCoEu6C8IR41apQWL1782PZPTk5WamrqY9sfeBTOH3yJ8wcgGDEIBgAAAFMLXb9+/XpfFxFIoqOjlZ6ermHDhvm6FJgQ5w++xPkDEKyCcoYYAAAA6CtGJgAAAGBqNMQAAAAwNRpiAAAAmFpQxq49Dnfv3lVxcbHOnTsnq9WqrKwszZs3z9dlIUi1t7erpKREv/32m5qbmzVq1CgtXLhQM2fO9HVpMJm///5bb7zxhuLi4rRlyxZflwMAjwUNcR/Z7Xa1t7ertLRUDQ0NWrt2reLj4zV58mRfl4Yg1NHRodjYWG3cuFE2m01VVVX6+OOPZbPZ9Mwzz/i6PJhIaWmpxo0bJ4fD4etSAOCxoSHug9bWVlVUVOjzzz9XZGSkkpKSlJmZqSNHjtAQ47GIiIjweHOZiRMnKjk5WVVVVZowYYK2b9+us2fPqqOjQ2PGjNF7772nhIQEH1aMYHTx4kVdv35dGRkZ+umnnyRJbW1tnD8AQYeGuA+uXbsml8ulxMRE99r48eN1+vRpH1YFM2ltbVV1dbXmzJmjY8eOqba2Vna7XVFRUaqrq1N0dLSvS0SQaW9vl91u17vvvqvLly+71zl/AIIRP1TXB62trYqMjPRYi4qKUktLi48qgpk4nU4VFRXpqaee0nPPPaewsDC1tLSorq5OLpdL48aNU0xMjK/LRJDZv3+/UlJSNH78eI91zh+AYMQNcR9ERER0a37v378vq9Xqo4pgFi6XS9u3b1dTU5MKCgpksVj00ksvqampScXFxWpqatLUqVO1fPnybv9pA7x1/fp1HT16VFu3bu32Oc4fgGDEO9X1QWtrq3JyclRUVOSek9u9e7fq6uq0Zs0aH1eHYOVyuVRSUqLq6mpt2LChx4ajqalJmzdv1qRJk5Sbm+uDKhGMjh49qh07drjPXFtbm9ra2hQdHa2SkhL3OucPQLDghrgPIiIiNG3aNO3atUurV69WY2OjysvLtXLlSl+XhiBmt9t16dIlbdy40aMZPn/+vIYNG6aEhARFRERoyJAhCglh+gkDJy0tTampqe7XJ0+e1PHjx7Vu3TpVV1dz/gAEHRriPsrPz9e2bdu0dOlSWa1WLViwgIQJPDYNDQ368ccfNWTIEC1fvty9np2dLZvNph07dujWrVsKDw9XamqqXn31VR9Wi2ATHh6u8PBw9+uoqCiFhoYqJiZG58+f5/wBCDqMTAAAAMDU+D4XAAAATI2GGAAAAKZGQwwAAABToyEGAACAqdEQAwAAwNRoiAEAAGBqNMQAAAAwNRpiAAAAmBoNMYA+u3PnjiwWi3bu3DloX/PEiRMqLCzstr5+/XpFR0cPWh0AgOBFQwzArz2sIV6xYoWOHz/ug4oAAMEmzNcFADCflpYWWa3Wfu0RHx+v+Pj4AaoIAGBm3BADeKgvv/xSSUlJioyM1CuvvKLq6mqPz1ssFm3ZssVjraioSBaLxf36xIkTslgs+uGHH5Sdna3hw4frtddekyR99dVXSktLU2xsrGJiYpSenq4zZ864f+369etVUFCge/fuyWKxyGKxKD093f25riMTtbW1ys7O1ogRIxQVFaVZs2bpwoULHs8kJSXp7bffVnFxsRITEzVixAjNnz9fjY2N/f7zAgAEJm6IAfTo0KFDysvL09KlS7Vo0SJVVla6G1lv5OXlKTc3VwcOHFBoaKgkqaamRq+//rqeeOIJtbW1ac+ePZoxY4bOnz+vp59+WitWrFBdXZ2+/vprHTt2TJI0fPjwHvdvbm5Wenq6QkJCVFJSooiICH3yySfu/caNG+d+9uDBg/rzzz9VXFysmzdvavXq1XrnnXdUVlbm9e8PABC4aIgB9Gjjxo2aPn26SktLJUmzZs1Sa2urNmzY4NV+c+fO1ebNmz3W1q1b5/7Y6XQqIyNDZ86c0c6dO1VYWOgeiwgJCdGUKVMeuX9paalqa2v1+++/Kzk5WZI0c+ZMJSQkqKioSJ9++qn7WZfLpYMHDyo8PFzSP415YWGhnE6nQkL4xhkAmA1/8wPopqOjQ5WVlcrKyvJYz87O9nrP2bNnd1urqqpSVlaWbDabQkNDNWTIEF26dEl//PGH4f1PnjypZ5991t0MS1JsbKwyMjJ06tQpj2dnzpzpboYlaeLEiWpvb1dDQ4PhrwsACHzcEAPoprGxUQ6HQ2PGjPFYt9lsXu/Z9dc2NzcrMzNTo0eP1meffabExERFRERoxYoVam1tNbz/7du3e6zPZrPp4sWLHmsjR470eD106FBJ8urrAgACHw0xgG5Gjx6tsLCwbjemN27c8HgdHh6utrY2j7Xbt2/3uOe/f9BOkk6fPq26ujodOnRIKSkp7vW//vrLq/SI2NhYXbp0qdv6jRs3FBsba3g/AIB5MDIBoJvQ0FClpqbqwIEDHuvffPONx+v4+HhVVVV5rB05cqRPX6OlpUXSf29nJenXX39VTU2Nx3NDhw7VgwcPet0vLS1NFy5c8GiKb9++rZ9//llpaWl9qgkAYE40xAB69OGHH+rkyZNatmyZDh8+rMLCQu3atcvjmezsbO3bt09ffPGFDh8+rCVLlujatWt92n/KlCmKjo7WW2+9pfLycpWWlmrRokUaO3asx3PJyclyOBzaunWrzp492+MtsCQtW7ZMiYmJmj17tsrKyvTdd98pMzNTYWFhWrVqlXd/CAAAU6AhBtCjuXPnqqSkREePHtX8+fNVXl6uvXv3ejyzdu1a5eTkqKCgQLm5uUpMTNTKlSv7tL/NZtO+ffvU0NCgefPmqaioSHa7XU8++aTHc3PmzNGbb76pTZs26YUXXlB+fn6P+w0bNkwnTpxQSkqK8vLytHjxYsXExOiXX37xiFwDAKAri8vlcvm6CAAAAMBXuCEGAACAqdEQAwAAwNRoiAEAAGBqNMQAAAAwNRpiAAAAmBoNMQAAAEyNhhgAAACmRkMMAAAAU6MhBgAAgKnREAMAAMDUaIgBAABgav8P/6B5mb8PHeIAAAAASUVORK5CYII=\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 23, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 23, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Timeout\n", + "\n> Recall that you can only use timeout when using processes, not threads." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "n_inputs = 50\n", + "job_time = 1" + ], + "outputs": [], + "execution_count": 24, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(n_workers=n_workers) as Q:\n", + "\n", + " for i in range(n_inputs):\n", + " sleep_sec = random.randint(0, job_time*2000) / 1000 # sleep between 0s and 2s (avg=1s).\n", + "\n", + " Q.put(function=time.sleep, args=sleep_sec,\n", + " timeout=job_time*1.8) # 1.8 < 2; timeout will occur on ~10% of jobs.\n", + "\n", + " Q.waitpb()\n", + "\n", + " results = Q.collect()\n", + " \n", + "title = '{} inputs, 0-2s job time, {} workers (timeout=1.8s).'.format(n_inputs, job_time, n_workers)\n", + "\n", + "plt = ezpq.Plot(results).build(color_by='cancelled',\n", + " color_pal=['blue', 'red'],\n", + " title=title)\n", + "\n", + "plt.save('imgs/{}xNx{}_timeouts.png'.format(n_inputs, n_workers))\n", + "plt" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "41eb98b8762841f7a0b16b2cadb4d807" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "/Users/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:706: UserWarning: Saving 6.4 x 4.8 in image.\n", + " from_inches(height, units), units))\n", + "/Users/donald/envs/mypy36/lib/python3.6/site-packages/plotnine/ggplot.py:707: UserWarning: Filename: imgs/50xNx10_timeouts.png\n", + " warn('Filename: {}'.format(filename))\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "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UjpCTk6OTpw40eH4hQsXlJOTY/p+AIDExYgCgA7cbrdGjRqlDz/8MOL4X//614jXBQUFqqmpiTi2Z8+eqL5Ga2urpG92TyXp0KFDOnPmTMR1Ho9Ht27duu/9vF6vjh8/HtHkXr58Wf/85z/l9XqjqgkA4Aw0uAA69dvf/lb79+/Xs88+q127dqmyslKbNm2KuKasrEwffPCB/vjHP2rXrl165pln1NDQENX9x40bp+zsbD3//PPavXu3qqurNXv2bA0cODDiuqFDhyoQCOidd96Rz+frdJdWkp599lkVFRVp6tSp2rJli/72t7+ptLRUqampeumll7r2TQAAJCQaXACdmjZtmtavX69PPvlETz31lHbv3q2tW7dGXLNkyRLNmTNHFRUVKi8vV1FRkV588cWo7p+Xl6cPPvhATU1Nmj59ulatWqWqqip997vfjbjuySef1C9/+Uu99dZbGjt2rBYvXtzp/Xr37q19+/ZpxIgRWrRokebOnat+/frps88+i4gIAwA4n8swDMPqIgAAAICewg4uAAAAHIUGFwAAAI5CgwsAAABHocEFAACAo9DgAgAAwFFocAEAAOAoNLgAAABwFBpcAAAAOAoNLgAAAByFBhcAAACOQoMLAAAAR/k/O4a+Dk46YAwAAAAASUVORK5CYII=\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 25, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 25, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Logging\n", + "\n", + "Writing to a log is as simple as adding `log_file='/path/to/file.csv'`. \n", + "\nThe example below illustrates a simply real-world use case. The goal is to obtain the total count and size of files within various folders. One process will be spawned to enumerate each folder. By doing so in parallel, the entire operation only takes as long as the single-most long operation." + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Define the function to enumerate the files." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "import os, fnmatch\n", + "def enum_files(path, pattern):\n", + " '''https://stackoverflow.com/a/1724723'''\n", + " n, size = 0, 0\n", + " for root, dirs, files in os.walk(path, followlinks=True):\n", + " for name in files:\n", + " if pattern is None or fnmatch.fnmatch(name, pattern):\n", + " n += 1\n", + " size += os.path.getsize( os.path.join(root, name) )\n", + " \n", + " return (n, size)\n", + "\n", + "root_dir = os.environ['HOME']\n", + "\n", + "include_dirs = [os.path.join(root_dir, x)\n", + " for x in ['bin', 'Desktop', 'Documents', 'Downloads', 'Music', 'Pictures']]" + ], + "outputs": [], + "execution_count": 26, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "code", + "source": [ + "log_file = 'ezpq_log.csv'\n", + "\n", + "# first, remove existing log file.\n", + "if os.path.exists(log_file):\n", + " os.unlink(log_file)" + ], + "outputs": [], + "execution_count": 27, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Each result will be written to a CSV file and discarded. Afterward, we'll read the CSV back in and draw a plot.\n", + "\nNotice there is no call to `get()` or `collect()`. Because `auto_remove=True`, jobs are discarded; there is no completed queue to pull from." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(n_workers = len(include_dirs),\n", + " log_file=log_file, auto_remove=True) as Q:\n", + "\n", + " for path in include_dirs:\n", + " Q.put(name=path,\n", + " function=enum_files,\n", + " kwargs={'path': path, 'pattern': '*'})\n", + "\n Q.waitpb()" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=6), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "60e13de27e9049fb8cde7c89c03cdba0" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "Process 1:\n", + "Traceback (most recent call last):\n", + " File \"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n", + " self.run()\n", + " File \"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/process.py\", line 93, in run\n", + " self._target(*self._args, **self._kwargs)\n", + " File \"../ezpq/Queue.py\", line 587, in _job_wrap\n", + " raise ex_obj\n", + " File \"../ezpq/Queue.py\", line 578, in _job_wrap\n", + " out = _job.function(*args, **kwargs)\n", + " File \"\", line 9, in enum_files\n", + " size += os.path.getsize( os.path.join(root, name) )\n", + " File \"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/genericpath.py\", line 50, in getsize\n", + " return os.stat(filename).st_size\n", + "FileNotFoundError: [Errno 2] No such file or directory: '/Users/donald/bin/kudu/build/latest/bin/hive-home'\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + } + ], + "execution_count": 28, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Read the CSV file back in with pandas." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "date_cols = ['submitted', 'started', 'ended', 'processed']\n", + "\n", + "results\n", + "\n", + "df = pd.read_csv(log_file, parse_dates=date_cols)\n", + "\n", + "os.unlink(log_file)\n", + "\ndf.head()" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 29, + "data": { + "text/plain": [ + " qid id name priority lane timeout function \\\n", + "0 2db4adcb 2 /Users/donald/Desktop 100 NaN 0 enum_files \n", + "1 2db4adcb 5 /Users/donald/Music 100 NaN 0 enum_files \n", + "2 2db4adcb 6 /Users/donald/Pictures 100 NaN 0 enum_files \n", + "3 2db4adcb 3 /Users/donald/Documents 100 NaN 0 enum_files \n", + "4 2db4adcb 4 /Users/donald/Downloads 100 NaN 0 enum_files \n", + "\n", + " args kwargs \\\n", + "0 NaN {'path': '/Users/donald/Desktop', 'pattern': '*'} \n", + "1 NaN {'path': '/Users/donald/Music', 'pattern': '*'} \n", + "2 NaN {'path': '/Users/donald/Pictures', 'pattern': ... \n", + "3 NaN {'path': '/Users/donald/Documents', 'pattern':... \n", + "4 NaN {'path': '/Users/donald/Downloads', 'pattern':... \n", + "\n", + " submitted started \\\n", + "0 2019-03-12 23:55:52.432877 2019-03-12 23:55:52.542806 \n", + "1 2019-03-12 23:55:52.432944 2019-03-12 23:55:52.561550 \n", + "2 2019-03-12 23:55:52.432960 2019-03-12 23:55:52.567884 \n", + "3 2019-03-12 23:55:52.432895 2019-03-12 23:55:52.548391 \n", + "4 2019-03-12 23:55:52.432928 2019-03-12 23:55:52.555055 \n", + "\n", + " ended processed exitcode cancelled \\\n", + "0 2019-03-12 23:55:52.555101 2019-03-12 23:55:52.637417 0 False \n", + "1 2019-03-12 23:55:52.584082 2019-03-12 23:55:52.639257 0 False \n", + "2 2019-03-12 23:55:52.583016 2019-03-12 23:55:52.639970 0 False \n", + "3 2019-03-12 23:55:52.659204 2019-03-12 23:55:52.736533 0 False \n", + "4 2019-03-12 23:55:52.927651 2019-03-12 23:55:52.940752 0 False \n", + "\n", + " runtime output exception callback \n", + "0 0.012295 (8, 2223032) NaN NaN \n", + "1 0.022532 (57, 3311151) NaN NaN \n", + "2 0.015132 (4, 6338) NaN NaN \n", + "3 0.110813 (2037, 13147879277) NaN NaN \n", + "4 0.372596 (7541, 762292776) NaN NaN " + ], + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
qididnameprioritylanetimeoutfunctionargskwargssubmittedstartedendedprocessedexitcodecancelledruntimeoutputexceptioncallback
02db4adcb2/Users/donald/Desktop100NaN0enum_filesNaN{'path': '/Users/donald/Desktop', 'pattern': '*'}2019-03-12 23:55:52.4328772019-03-12 23:55:52.5428062019-03-12 23:55:52.5551012019-03-12 23:55:52.6374170False0.012295(8, 2223032)NaNNaN
12db4adcb5/Users/donald/Music100NaN0enum_filesNaN{'path': '/Users/donald/Music', 'pattern': '*'}2019-03-12 23:55:52.4329442019-03-12 23:55:52.5615502019-03-12 23:55:52.5840822019-03-12 23:55:52.6392570False0.022532(57, 3311151)NaNNaN
22db4adcb6/Users/donald/Pictures100NaN0enum_filesNaN{'path': '/Users/donald/Pictures', 'pattern': ...2019-03-12 23:55:52.4329602019-03-12 23:55:52.5678842019-03-12 23:55:52.5830162019-03-12 23:55:52.6399700False0.015132(4, 6338)NaNNaN
32db4adcb3/Users/donald/Documents100NaN0enum_filesNaN{'path': '/Users/donald/Documents', 'pattern':...2019-03-12 23:55:52.4328952019-03-12 23:55:52.5483912019-03-12 23:55:52.6592042019-03-12 23:55:52.7365330False0.110813(2037, 13147879277)NaNNaN
42db4adcb4/Users/donald/Downloads100NaN0enum_filesNaN{'path': '/Users/donald/Downloads', 'pattern':...2019-03-12 23:55:52.4329282019-03-12 23:55:52.5550552019-03-12 23:55:52.9276512019-03-12 23:55:52.9407520False0.372596(7541, 762292776)NaNNaN
\n", + "
" + ] + }, + "metadata": {} + } + ], + "execution_count": 29, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "# ezpq.Plot requires a dictionary of job data records.\n", + "records = df.to_dict(orient='records')\n", + "\n", + "plt = ezpq.Plot(records).build(color_by='name', bar_width=5)\n", + "\n", + "# plt.save('...')\n", + "plt" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "iVBORw0KGgoAAAANSUhEUgAAAyEAAAGxCAYAAAB1F7mZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzs3XtYVOX+NvCbOYkM4wwDchQUT2EeUjC11EBEy4YyLw8pJooa4jbzkOL5TU3tV0phmKVWgiiWecoNCFmJW9uZKf7MvROREEEUYWBABjEZZt4/fF2vA6igMEN6f65rrotZz7Oe9Z01q1z3rJONyWQygYiIiIiIyEJE1i6AiIiIiIieLAwhRERERERkUQwhRERERERkUQwhRERERERkUQwhRERERERkUQwhRERERERkUQwhRERERERkUQwhRERERERkUQwhRERERERkUQwhRERERERkURJrF/Awbty4gYyMDPj4+MDOzs7a5RAREVE9lZaW4saNG40ylp2dHVQqVaOMRUSW9bcMIRkZGfDz88OpU6fg6+vbaOOaTCaUl5dDoVDAxsam0cZ9EphMJhiNRohEIq67BuJ293C4zT08bnMPj9vdw7mzzRmNRmzYsAEGg6FRxpVIJHjrrbcYRIj+hv6WIaSpmEwm6PV62Nvb8x+Xh3DnH2ZqGG53D4/b3MPhNvdouN013J1tzmQywWAwoFevXrC3t3+kMfV6PU6fPo0bN24whBD9DTGEEBERkUXZ29szOBA94fhTDhERERERWRRDCBERERERWRRDCBERERERWRRDCBERERERWRRDCBERERERWRRDCBERERERWRRDCBERERERWRSfE1KDwWCAwWD4WzyIqsh4rda01iKXRx5XIuFmQURERERNh3ubNeh0OojF4r/FU4TfvfFOrWkr7D565HHd3d0feQwiIiIiontpNiHk3//+NxISEnDt2jW0atUKU6ZMwfPPP2/tsoiIiIiIqJE1ixBy5swZfPHFF5g3bx58fHxw/fp13Lx509plERERERFRE2gWISQhIQGvv/46nn76aQCASqWyckVERERERNRUrB5CqqurceHCBfTp0wcRERG4efMmevXqhalTp0Iul1u7PCIiIiIiamRWvwVUaWkpDAYD/vWvf2HVqlXYsGEDSktL8cUXX5j1u3r1KtLT05Geno5z585ZqVoiIiIiInpUVj8S0qJFCwCARqOBk5MTAGD06NFYs2aNWb9NmzZhxYoVFq+PiIiIiIgal9WPhNjb28PJyemBt8SdNm0aTp06hVOnTmH79u0Wqo6IiIiIiBqb1Y+EAMDQoUORlJSE3r17o0WLFtizZw/69Olj1sfNzQ1ubm5WqpCIiIiIiBpLswgho0ePxvXr1zFjxgyIxWL07t0bU6dOtXZZRERERETUBJpFCBGLxQgPD0d4eLi1SyEiIiIioiZm9WtCiIiIiIjoydIsjoQ0Jw4ODmjdujVEouafz1Yao2pNay1ytkIlRERERET1xxBSg0QigUQi+VuEEDd4WLsEIiIiIqIGa/572kRERERE9FhhCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIotiCCEiIiIiIouSWLuA5sZgMMBgMEAkar75zGi4ds82kcTlkceXSLhZEBEREVHT4d5mDTqdDmKxGDY2NtYu5Z5uXHvnnm12Lh898vju7u6PPAYRERER0b0035/7iYiIiIjoscQQQkREREREFsUQQkREREREFsUQQkREREREFsUQQkREREREFsUQQkREREREFsUQQkREREREFsUQQkREREREFsUQQkRERERE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XnValpeXp6KiIhdVhIoaMmSIEhISqnw7CQkJGjJkyH3Xt2/fXikpKRXqu0WLFvr6668rWBkehhACAADcQq9evTR9+nSlp6dr586d+t///V9Nnz69Ws+CXL16VQEBASosLFRsbKwWLlzotP706dPy8PCosnuYPMi6deueyL/NlClTNHPmTMd75+fnJz8/P0VERGjKlCmO+9J8//336tGjx0P7K+vvgofjcCwAAOAWRowYobCwMG3btk05OTmqW7eu/uM//kPdu3d3dWkus3HjRsXGxpa6iWNVstvtstlsjjvX3096err69OljUFWVJz09XStXrnQ8zs7Olq+vr77//nt169ZNjRs31uuvv25YPXfOqa1umAkBAABuo3v37poxY4bmz5+vGTNmVOsAIpV/Rz81NVVNmjSR2WxWRESE5syZ41i3ceNGtWvXThaLRTExMdq+fbtjXWxsrN555x3Fxsaqdu3a2rVrlzZs2KBWrVrJbDYrNDRUkydPdtrW2rVrHbVt2bJFLVq0kNls1siRI1VYWOjUdvny5WrevLksFou6deumI0eOOG172rRp6tq1q8xmszp06KAzZ8441v/2t79VZGSkzGazYmJitG3btvu+/pUrV6pRo0by9/fXm2++WWr9yZMndf369TJvDtmiRQt17txZhw4dkiQ1aNBAGzZskCTZbDbNnj1bzZo1k9lsVosWLbRv3z699dZb2r59uyZOnCg/Pz+NGDFCUsnV3O5+jVOnTtXo0aMl/Wv2KiUlRQ0bNnTUcvz4cb300ksKDAxU48aNtWDBvy5WsGfPHr3wwgt65plnFBQUpGHDht33PXhSEEIAAADckM1m08aNGxUXF/dI7a9fv66xY8dq2bJlys/P14EDBxQbGytJOnDggIYOHark5GTl5uZqxowZeuWVV5Sdne14fkpKipKTk1VQUKCYmBiNGTNGU6ZMUX5+vk6cOKGBAwc62h48eFC1a9dWo0aNlJubq/79+2vq1KnKy8tT9+7dtWbNGkfbrVu3auLEiUpJSVFWVpa6d++uuLg43b5929Hmk08+0bx585STk6N69epp2rRpjnVt27bVvn37lJeXp5EjR2rQoEG6ceNGqdd/5MgRjR07VosXL1ZWVpYsFov27Nnj1CY9Pf2+7+d3332nv//974qJiSm17qOPPtKSJUv0xRdf6Nq1a/ryyy9Vt25dzZo1S506dXK8b6mpqQ/5K/3Lhg0bdODAAe3du1c3btxQ9+7d1a9fP/30009at26dPvjgA2VkZEiSfv3rX6tfv366cuWKzp07pzfeeOORt+OuCCEAAABuaOfOnYqKilJISMgjP8fb21s//PCDrl27poCAALVp00aStGjRIo0bN04dO3aUp6en+vTpo9atW2vdunWO544cOVKtW7eWp6enatSoIR8fH504cULZ2dny8/PTCy+84Gh79wxNenq6mjZtqhEjRshkMmnUqFFq1aqVo+2KFSs0evRotW/fXj4+Pnr77bd18+ZN7dixw9FmzJgxatmypXx8fDR06FDt27fPsW7YsGEKDAyUyWTSxIkTVVRUpMOHD5d67atWrdJLL72kHj16yNvbW2+//bb8/f2d2pQ1sxQaGip/f38NGDBA48eP15gxY0r1vXDhQiUlJally5by8PBQ06ZNFRUV9Uh/k/tJSEjQM888o5o1ayo9PV316tXT+PHj5e3trZ/97Gf61a9+pU8//VSS5OPjozNnzujixYvy9fVVhw4dHmvb7oAQAgAA4IbuPtxJKgkY914prKioSB4eHvLy8lLt2rW1Zs0arV69WhEREerSpYu+/fZbSSWHAM2bN08Wi8Xx386dO3Xx4kVHX/fuVK9evVqHDh1S06ZN9Ytf/ELp6ell1nbx4kVFRkY6Pffuvi5cuKAGDRo4Hnt6eioyMlIXLlxwLAsNDXX8f61atVRQUOB4/OGHHyo6Olp16tSRxWLR1atXnWZw7ri3Di8vL9Wv/6/7HBQUFGjPnj3q1q2b0/MyMzOVl5en48ePKyEhocxbDZw9e1ZNmjQptfxx3P0enT59Wvv373f6+/z3f/+3MjMzJUkff/yxbty4oZiYGLVo0UIff/xxpdbiCtXvLBgAAIAnQHp6utPOZmRkpE6dOuXU5uTJkwoLC5O3t7ckqUePHurRo4cKCwuVnJyswYMH69y5c4qMjNSUKVMeeNnce3e+Y2Ji9MUXX6i4uFifffaZBg4cqJycHN26dUtHjx7Viy++KEkKCwvT2bNnnZ579uxZtW7dWpJUv359nT592rHOZrPp3LlzTgHhfrZv3673339fW7ZsUcuWLeXp6Sl/f3/H/cnuFhYWpgMHDjgeFxcXOwWdjIwMdejQQb6+vg/d7r0iIyN14sQJx2u6W1mhpXbt2k6HjN0JE/d7XmRkpF588UVt3bq1zO03btxYK1askN1u17Zt29SrVy917ty50oORkZgJAQAAcDPnzp1Tdna20/kJw4YN0/Lly/XNN984duRnzJihoUOHSpIuXbqkL7/8UgUFBfL29pbZbHZc4So+Pl6LFy/Wjh07ZLPZdPPmTW3ZskXnz58vc/uFhYVKTU1VXl6evLy8ZLFYHDMu69atU8+ePR1XdIqLi9OxY8eUlpYmq9Wq1NRUx8ndd+pOSUnRrl27VFRUpFmzZsnHx0cdO3Z86PuQn58vk8mkwMBAWa1Wvffee7p27VqZbQcNGqT169dr8+bNju3k5eU51j/O1bzi4+M1ffp0/fDDD7Lb7Tp+/Ljj5PmQkBD9+OOPTu3btGmj1NRUFRcX6x//+Ie++uqrB/bfp08fnT59Wn/5y190+/ZtWa1WHTp0SLt375ZUcs5MVlaWPDw8nP4WTzJCCAAAgJtJT0/Xyy+/7PRrebdu3TR37lyNHz9eFotFnTp1UocOHZSYmCipZIYhOTlZ4eHhslgsSklJUVpamqSSWY3ly5dr8uTJqlu3rqKiojR79mzZbLb71pCWlqbGjRvLbDbrrbfe0qpVq+Tr61tqZ75u3bpavXq1kpKS5O/vr4yMDPXt29exvmvXrpo9e7ZGjBihoKAgbdq0SWvXrlWNGjUe+j707t1bcXFxat68uaKiouTt7a2IiIgy20ZHR2vp0qV67bXXFBwcrJycHLVr105SyWWH169fX+EQ8pvf/EYjR45U3759ZTab9ctf/lK5ubmOdWvWrJG/v79GjRolqeRE9r/97W+yWCyaPXu2Xn311Qf27+fnp4yMDK1Zs0YREREKCgpSfHy8I3BlZGSoVatW8vPz06BBg7RgwQI1bNiwQq/FXXjYy5rPcnP79u1T27ZttXfv3jKvYFBRNptNmZmZCg0Nlacn+aw87Ha74zrXZU1L4v4YdxXDmKs4xlzFMe4q5s6Ys9vtWrJkiTp16iSLxfJYfV65ckXbt29XfHy8wsLCKqnS+8vMzNS0golV0rfFFqA/NlvgtCwuLk7x8fHq379/lWyzoqxWq0JDQ3Xs2DEFBAS4upxHtnv3bsXHx2v//v2uLgX/xLcPAACAm+nSpcsj3a3baLm5uUpMTHyiAohU8gNCUlKSq8vAXTgxHQAA4BH8v6slN+tr1qxZpfZ778nmkjRlypRK3UZlCQ4O1oQJE1xdRrk9//zzri4B92AmBAAAAIChCCEAAAAADEUIAQAAAGAozgkBAAAoh2PHjlVqf3duNAhUJ4QQAACAhwgMDNQzzzxTJX1zuWdUR4QQAACAhzCZTI47hAN4fPxrAgAAeARWq7XK+ibgoLphxAMAADxEZmamLly4UCV9e3t76+c//3mV9A24K66OBQAAAMBQzIQAAACUgxF3TAeedsyEAAAAADAUIQQAAACAoTgcCwAA4BH8sc4/f7u9dKJS+w3wlRZUao+A+2MmBAAAAJVqyJAhSkhIqPLtJCQkaMiQIfdd3759e6WkpJS5buvWrQoNDb3vc2fOnKnRo0c/ZoW4H0IIAACAm7p69aoCAgJUWFio2NhYLVy40Gn96dOn5eHhoVu3bhle27p169SrVy/Dt/u4pkyZopkzZz603TvvvHPfAIPHRwgBAABwUxs3blRsbKx8fHwM26bdbldxcfFD26Wnp6tPnz4GVFS5ntS6nzaEEAAAADdV3h3m1NRUNWnSRGazWREREZozZ45j3caNG9WuXTtZLBbFxMRo+/btjnWxsbF65513FBsbq9q1a2vXrl3asGGDWrVqJbPZrNDQUE2ePNlpW2vXrnXUtmXLFrVo0UJms1kjR45UYWGhU9vly5erefPmslgs6tatm44cOeK07WnTpqlr164ym83q0KGDzpw541j/29/+VpGRkTKbzYqJidG2bdvu+/pXrlypRo0ayd/fX2+++Wap9SdPntT169edbg75xz/+UcHBwQoPD9fcuXMdy+8+1OvOjFNqaqoaNmwof39/TZo06b514OEIIQAAAG7IZrNp48aNiouLe6T2169f19ixY7Vs2TLl5+frwIEDio2NlSQdOHBAQ4cOVXJysnJzczVjxgy98sorys7Odjw/JSVFycnJKigoUExMjMaMGaMpU6YoPz9fJ06c0MCBAx1tDx48qNq1a6tRo0bKzc1V//79NXXqVOXl5al79+5as2aNo+3WrVs1ceJEpaSkKCsrS927d1dcXJxu377taPPJJ59o3rx5ysnJUb169TRt2jTHurZt22rfvn3Ky8vTyJEjNWjQIN24caPU6z9y5IjGjh2rxYsXKysrSxaLRXv27HFqk56e7vR+Zmdn69SpUzp79qy++uorJSYmavPmzfd9j7/++mt999132rt3r5YtW/bA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\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 30, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 30, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Callback\n", + "\nIf instantiated with a callback, `ezpq.Queue` will pass a dictionary of job data as the single argument to the callback function. It does this synchronously, so the callback must not take too much time." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "def slow_callback(x):\n", + " time.sleep(0.5)" + ], + "outputs": [], + "execution_count": 31, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(n_workers=n_workers, callback=slow_callback, poll=1) as Q:\n", + " for _ in range(n_inputs):\n", + " Q.put(time.sleep, 1)\n", + " Q.waitpb()\n", + " results = Q.collect()" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "42eddf20694643e4882d46c520208800" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + } + ], + "execution_count": 32, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "code", + "source": [ + "ezpq.Plot(results).build(show_legend=False)" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "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TQYgmF566aXvfD7+rnfI+CGWh6ExY8bojjvu0IQJE9SrVy/f9aNHj2rp0qUaM2ZMmzYSLkxsFkm0yUzL/Ou8B59uVt4A7G/ZsmUd/tZfloehFStWaPz48UpNTdV5552n5ORkVVZW6pVXXlFUVJQefPDBDt0gAACAJJ155plBeYFm+aXusGHD9P7772vu3Lk6ePCgioqKdPDgQV177bV6//33NWzYsA7fJAAAwNKlS1v9fqH2atOKqampfu9XZhITa9YS1XrTMg/Xaj0VesDZPB6P3nvvPcXExGjo0KEdtm5Aw9BZZ52lRx99VMOGDdPw4cO/98nR5XIpISFBo0aN0sKFC5WQkNBhm7UDE2vWEtV60zIP12o9FXrA2VavXq13331XTU1Nys7O1owZM/Tqq6/q008/1TXXXNPmdQMahkaOHOn7ydIjR478wX8Uampq9D//8z8qLS3VU0891ebNAQAAfK24uFhr1qxRbW2t7r77bs2YMUMjR47Uww8/HPxhaP369b5fb9iwIaCF//jHP+ryyy9v06bsjGq9WSckVOup1gOwj+joaPXo0UMJCQmqrq6WJMXGxqq2trZd6wbtjVonTJigjRs3Bmv5kDGxZi1RrTctc6r1AOwoKytLTz75pGbOnOm79uyzz6pv377tWjdow1B8fLyysrKCtTwAADDMn/70J3311Vd66qmn1NDQoMsuu0wRERFauHBhu9YN2jAEAADQkebPn+/3cc+ePZWamtruJinDkEUm1qwlqvWmZW73aj0VesBMI0aMCMq6DEMWmVizlqjWm5a53av1VOgBM23atCmgx/3Lv/yLpXUZhgAAQFhwu916++23lZ6ersTERFVVVam8vFw//elPfe9X5vV6La/LMGQR1XqzTkio1lOtB2Af3bp104033qjx48f7rr366qvas2ePbrrppjavyzBkkYk1a4lqvWmZU60HYEdvvfWW/vVf/9Xv2rhx47RmzZp2rWvOszsAAAhriYmJeu211/yu7dy5U0lJSe1al5MhAAAQFq677jotXbpUTz/9tBITE1VZWakvv/xSt956a7vWZRiyyMSatUS13rTM7VCtpz4P4NuGDRumdevWac+ePTp06JDGjBmjf/qnf/K9f2pbMQxZZGLNWqJab1rmdqjWU58H0Jru3btrwoQJHbomwxAAAAgLgd4OW7p0qaV1GYYsolpv1gkJ1Xqq9QDsY/DgwSoqKtKECRN8P2do586dmjRpUru+iTrkw9CJEye0du1avf/++6qpqVGfPn00c+ZM3xGY2+3WqlWrVF5eruTkZOXm5iojIyNk+zWxZi1RrTctc6r1AOzoww8/1O23364BAwb4rk2cOFEPPPCA7rnnnjavG/Jn9+bmZiUkJOiOO+7Q5s2b9etf/1oPPPCA9u3bp6amJuXn52vUqFHatGmTZs2apWXLlunIkSOh3jYAAOhkBw4cUN++ff2u9evXT263u13rhnwYio6O1uzZs3XqqafK5XJp6NChGjJkiEpKSrSkFDXCAAAVoElEQVR3714dO3ZM2dnZioqK0rhx45SWlqbi4uJQbxsAAHSyQYMG6b//+79VW1srSaqrq9O6dev04x//uF3rhvw22bc1Njbq008/1bRp03TgwAGlp6f73Z4YOHBguyfA9jCxZi3Zu1pfdqDZ8tcEWv82vVofGWm7pwgABluwYIFWrFihnJwcxcTEqKGhQUOHDm3XW3FINhuGPB6PVq5cqUGDBmnEiBH65JNPWvzsgLi4OFVWVrb42oqKClVUVEiSSkpKgrZHE2vWkr2r9bffXW/5awKtf5terY+NDf470ANAoPr06aNly5bp0KFDqq6uVkJCgnr37t3udW0zDHm9Xq1Zs0bV1dXKy8uTy+VSTEyM6urq/B5XV1enmJiYFl9fWFiovLy8ztouAAAIkd69e3fIEPQ1WwxDXq9Xa9euVVlZmfLz833DTlpamrZu3SqPx+O7RVFWVub3brVfmzdvnqZPny7p5MlQTk5OUPZKtd5+JyR5C63fJgu0/m16tR4A7OS+++7T9ddfr4iIls/hO3bs0MGDBzV79mzL69piGCosLFRpaanuuOMOv2P54cOHq2vXrtq2bZuysrK0e/duud1ujRkzpsUaKSkpSklJCfpeTaxZS/au1g8+PXhrm16tBwA7KSoq0q9+9atWh6FevXpp27Zt4TkMVVZW6k9/+pOioqJ09dVX+65nZ2dr5syZWrx4sQoKCrR582YlJSVp0aJFio+PD+GOAQBAKLhcLq1evbrVF2sNDQ367LPP2rRuyIehpKQkPf3009/5+fT0dC1fvrwTdwQAAOwqPj6+1ZOhU045RTNmzGjTmiEfhsKNiTVriWq90zPnHeIBhIucnBxFRUV16JoMQxaZWLOWqNY7PXPeIR5AOJg1a1ZQXpgyDAEAgLAwa9asoKzLMGQR1Xr7nZBQrQcAtAfDkEUm1qwlqvUmZg4ApuDZHQAAGI1hCAAAGI3bZBaZULNuDdV6Z2ROhR4AWmIYssiEmnVrqNY7I3Mq9ADQUvi/1AUAAGgHToYsolpvvxMSqvUAgPZgGLLI1Jo11XrzMgcAU/DsDgAAjMbJkEVOahZZQZssfDKnMQYA1jAMWeSkZpEVtMnCJ3MaYwBgTXi81AUAAAgSToYsok1mvxMS2mQAgPZgGLLI1GYRbTLzMgcAU/DsDgAAjMYwBAAAjMZtMovCrWbdUajW2y9zKvQA0DEYhiwKt5p1R6Fab7/MqdADQMew10tdAACATsbJkEVU6+13QkK1HgDQHgxDFplas6Zab17mAGAKnt0BAIDRGIYAAIDRuE1mkV1r1sFGtT50mVOhB4DgYhiyyK4162CjWh+6zKnQA0BwmXW8AQAA8C2cDFlEtd5+p2JU6wEA7cEwZJGpNWuq9eZlDgCm4NkdAAAYjWEIAAAYjdtkFoW6Zh0qTqrWB1qrlzqvWk99HgBCh2HIolDXrEPFSdX6QGv1UudV66nPA0DomHW8AQAA8C2cDFlEtd5+p2JWq/WB1uolqvUAYAKGIYtMrVlTrTcvcwAwBc/uAADAaAxDAADAaNwms4hqPdX69qBCDwD2wzBkEdV6qvXtQYUeAOzHrOMNAACAb+FkyCKq9fY7FaNaDwBoD4Yhi0ytWVOtNy9zADAFz+4AAMBoDEMAAMBo3CaziGo91fpAUKEHgPDBMGQR1Xqq9YGgQg8A4cOs4w0AAIBv4WTIIqr19jsVo1oPAGgPhiGLTK1ZU603L3MAMAXP7gAAwGgMQwAAwGjcJrOIaj3V+m+iQg8A4Y9hyCKq9VTrv4kKPQCEP7OONwAAAL7FFidD27dvV1FRkcrLy/Wzn/1MN998s+9zbrdbq1atUnl5uZKTk5Wbm6uMjIyQ7ZVqvf1OxajWAwDawxbDUEJCgmbOnKn/+7//U01Nje96U1OT8vPzNWXKFC1btkxvvfWWli1bprVr1yo+Pj4kezW1Zk213rzMAcAUtnh2P+ecczR69Gj17NnT7/revXt17NgxZWdnKyoqSuPGjVNaWpqKi4tDtFMAAOA0tjgZ+i4HDhxQenq63yvygQMHyu12h2xPbWmTWW07SdYaT53Bzm0yGl0AgPaw9TDU0NCguLg4v2txcXGqrKxs8diKigpVVFRIkkpKSoK2p7a0yay2nSRrjafOYOc2GY0uAEB72HoYiomJUV1dnd+1uro6xcTEtHhsYWGh8vLyOmtrAADAIWw9DKWlpWnr1q3yeDy+21JlZWUaP358i8fOmzdP06dPl3TyZCgnJycoe2pLm8xq20my1njqDHZukwEA0B62GIaam5vV3Nwsj8cjj8fj+56c4cOHq2vXrtq2bZuysrK0e/duud1ujRkzpsUaKSkpSklJCfpe29IsCmbbqbPYuU0GAEB72GIYeuyxx7R582bfx8XFxTrvvPN04403avHixSooKNDmzZuVlJSkRYsWhaxWDwAAnMcWw9Bll12myy67rNXPpaena/ny5Z28IwAAYApbDEPhhGp9aKr11OcBAMHCMGQR1frQVOupzwMAgsUWP4EaAAAgVDgZsohqPW0yAICzMAxZRLWeYQgA4CzcJgMAAEZjGAIAAEbjNplFVOuDW62nQg8A6GwMQxZRrQ9utZ4KPQCgs3GbDAAAGI2TIYuo1tMmAwA4C8OQRVTrGYYAAM7CbTIAAGA0hiEAAGA0bpNZRLW+Y6r1VOgBAHbBMGQR1fqOqdZToQcA2AW3yQAAgNE4GbKIaj1tMgCAszAMWUS1nmEIAOAs3CYDAABGYxgCAABG4zaZRVTrA6/WU58HAIQDhiGLqNYHXq2nPg8ACAfcJgMAAEbjZMgiqvW0yQAAzsIwZBHVeoYhAICzcJsMAAAYjWEIAAAYjdtkFlGtb1mtp0IPAAhnDEMWUa1vWa2nQg8ACGfcJgMAAEbjZMgiqvW0yQAAzsIwZBHVeoYhAICzcJsMAAAYjWEIAAAYjdtkFnVGtd5utXrpH7fJAABwGoYhizqjWm+3Wr10chhKSkoK9TYAAOhwvNQHAABG42TIos6o1tutVi+dPBkCAMCJGIYsMrla39TUFOptAADQ4bhNBgAAjMbJkEUmtMl441UAgEkYhiwyoU3GG68CAEzCbTIAAGA0ToYsMrVNBgCAUzEMWWRqmwwAAKfiNhkAADAawxAAADAat8ksckq1nvo8AAAnMQxZ5JRqPfV5AABO4jYZAAAwGidDFlGtBwDAWRiGLKJaDwCAs3CbDAAAGI1hCAAAGI3bZBaFW7WeCj0AAN+PYciicKvWU6EHAOD7cZsMAAAYjZMhi6jWAwDgLGExDNXW1mr16tX685//rJiYGM2YMUNZWVkh2QvVegAAnCUshqHCwkKdOHFC69evV2VlpW677Tb169dPI0eODPXWAABAmLP99ww1NjaquLhYl19+uWJjY5Wenq4pU6bopZdeCvXWAACAA9h+GPr888/l9XrVv39/37UBAwbowIEDIdwVAABwCtvfJmtsbFRsrH/VPC4uTg0NDX7XKioqVFFRIUkqKSnptP0BAIDwZvthKDo6usXgU19fr5iYGL9rhYWFysvL68ytAQAAB7D9bbK+fftKkt9tsbKyMqWlpfk9bt68edqzZ4/27NmjRx55pFP3CAAAwpfth6Ho6GiNGTNGGzduVH19vdxut1588UVNnjzZ73EpKSnKzMxUZmamhgwZEqLdAgCAcGP722TSyVOfgoICXXXVVYqJidEll1xCrR4AAHSIsBiGunfvrltuuSXU2wAAAA5k+9tkAAAAwcQwBAAAjMYwBAAAjMYwBAAAjBYW30Bt1dc/pLGjfxK1x+PRoUOHdPDgQUvvWu8EXq9Xzc3NioiIkMvlCvV2Oo2pmZuat0TmZE7moVRVVaWKigodOnSo3WvV1tYG/FhHDkPl5eWSpJycnNBuBAAAtElKSkq714iMjGzxll6tcXm9Xm+7fzeb+eqrr/TCCy8oPT29xdt2tEdJSYlycnL0yCOP8IMdDUHm5iFz85C5vdTU1Khfv34d8u93bGys4uPjf/BxjjwZ6tOnj2bPnh209YcMGaLMzMygrQ/7IXPzkLl5yNxc5twcBQAAaEXEkiVLloR6E+Gke/fumjhxonr06BHqraCTkLl5yNw8ZG42R37PEAAAQKC4TQYAAIzGMAQAAIzmyDZZMNTW1mr16tX685//rJiYGM2YMUNZWVmh3hbaYfv27SoqKlJ5ebl+9rOf6eabb/Z9zu12a9WqVSovL1dycrJyc3OVkZERwt2iI5w4cUJr167V+++/r5qaGvXp00czZ87UhAkTJJG7UxUUFOjdd99VQ0ODevTooSlTpmjmzJmSyBz/nxcBWb58uTc/P99bV1fnLSsr8+bk5HjffffdUG8L7VBcXOx98803vQ888ID3nnvu8V0/ceKE95prrvE+9thj3uPHj3tfe+0176WXXuo9fPhwCHeLjtDQ0OB95JFHvBUVFV6Px+P96KOPvJdeeqm3pKSE3B3M7XZ7GxsbvV6v11tZWemdP3++d9euXWQOH06GAtDY2Kji4mL94Q9/UGxsrNLT0zVlyhS99NJLGjlyZKi3hzY655xzJEn79+9XTU2N7/revXt17NgxZWdnq0uXLho3bpyeeeYZFRcXa+rUqfriiy+0atUq/fWvf1VERIRSU1N11113heqPAQuio6P9fgbZ0KFDNWTIEJWUlKihoYHcHSotLc3vY5fLpYMHD/J3HT4MQwH4/PPP5fV61b9/f9+1AQMG6M033wzhrhAsBw4cUHp6ut97FA0cOFBut1uStHHjRvXt21d5eXmSpNLS0pDsE+3X2NioTz/9VNOmTSN3h3vooYe0fft2HTt2TElJSTr33HP1xhtvkDkk8Q3UAWlsbGzx3iZxcXG+N4SFszQ0NCguLs7v2jfzjoyMVHV1tSorKxUZGakzzzwzFNtEO3k8Hq1cuVKDBg3SiBEjyN3hrrzySj3++ONasWKFJkyY4MuWzCExDAUkOjq6xeBTX1/foe97BvuIiYlRXV2d37W6ujpf3nPmzFFCQoIWL16sa6+9Vk888UQotol28Hq9WrNmjaqrq3XzzTfL5XKRuwFcLpcGDRqkqKgobdq0iczhw22yAPTt21fSydsnX997Lisra3EfGs6QlpamrVu3yuPx+I7Py8rKNH78eElSfHy85s+fL+nk9xvddtttGjRoEA2UMOH1erV27VqVlZUpPz/f9w8fuZvD4/GooqJCmZmZZA5JnAwFJDo6WmPGjNHGjRtVX18vt9utF198UZMnTw711tAOzc3NOn78uDwejzwej44fP66mpiYNHz5cXbt21bZt23TixAm9/vrrcrvdGjNmjCTp9ddfV1VVlaSTR+pdunTx+54D2FthYaFKS0uVl5fnd/ub3J2ptrZWO3bsUH19vTwejz7++GM999xz+slPfkLm8OHtOAJUW1urgoIC388Z+sUvfsHPGQpzjz76qDZv3ux37bzzztONN96o8vJyFRQUqLy8XElJSZo3b57v1eCGDRv06quvqra2Vj169NCFF17o+5klsLfKykrNnTtXUVFRioiI8F3Pzs7WzJkzyd2BamtrtWzZMu3fv18ej0cJCQk6//zz9Ytf/EIul4vMIYlhCAAAGI7zPgAAYDSGIQAAYDSGIQAAYDSGIQAAYDSGIQAAYDSGIQAAYDSGIQAAYDSGIQAAYDSGIQABO3LkiFwulzZs2NBpv+fOnTt15513tri+ZMkSde/evdP2AcC5GIYA2Np3DUNz587Vjh07QrAjAE7Du9YD6HQNDQ2+d4tvq379+qlfv34dtCMAJuNkCMB3WrdundLT0xUbG6tJkybp008/9fu8y+XS8uXL/a6tXLlSLpfL9/HOnTvlcrn07LPPKjs7Wz179tQvf/lLSdLDDz+ssWPHKiEhQaeccoomTpyot99+2/e1S5YsUV5enurq6uRyueRyuTRx4kTf5759m8ztdis7O1u9evVSXFycLrjgAu3du9fvMenp6br++uu1evVq9e/fX7169dLFF1/se3dyAObhZAhAq7Zv367c3FxdddVVmjVrlvbs2eMbYtoiNzdXOTk5evLJJ33vGF9eXq4rrrhCp512mo4fP65NmzZp/Pjx+uCDD/TjH/9Yc+fO1WeffaZHH31URUVFkqSePXu2un5NTY0mTpyoLl26aO3atYqOjtbSpUt966Wmpvoe+/TTT+svf/mLVq9era+++kr/9m//phtuuEGbN29u858PQPhiGALQqjvuuEPjxo3T+vXrJUkXXHCBGhsblZ+f36b1pk+frrvvvtvv2u9//3vfrz0ejyZPnqy3335bGzZs0J133um7FdalSxeNHj36e9dfv3693G63PvroIw0ZMkSSNGHCBKWlpWnlypVasWKF77Fer1dPP/20unXrJunkUHbnnXfK4/GoSxcOzAHT8LceQAvNzc3as2ePZsyY4Xc9Ozu7zWtOnTq1xbWSkhLNmDFDycnJioiIUFRUlEpLS/XJJ59YXn/Xrl0aNmyYbxCSpISEBE2ePFmvv/6632MnTJjgG4QkaejQoTpx4oQqKyst/74Awh8nQwBaqKqqUlNTk5KSkvyuJycnt3nNb39tTU2NpkyZosTERN17773q37+/oqOjNXfuXDU2Nlpe//Dhw63uLzk5WR9++KHftfj4eL+Pu3btKklt+n0BhD+GIQAtJCYmKjIyssVJyZdffun3cbdu3XT8+HG/a4cPH251zW9+U7Ukvfnmm/rss8+0fft2ZWRk+K4fPXq0TS2xhIQElZaWtrj+5ZdfKiEhwfJ6AMzBbTIALURERCgzM1NPPvmk3/UnnnjC7+N+/fqppKTE79pLL70U0O/R0NAg6R+nMpL0xhtvqLy83O9xXbt21bFjx35wvbFjx2rv3r1+A9Hhw4f18ssva+zYsQHtCYCZGIYAtOrWW2/Vrl27NGfOHL3wwgu68847tXHjRr/HZGdna8uWLbr//vv1wgsv6PLLL9fnn38e0PqjR49W9+7d9etf/1ovvvii1q9fr1mzZqlv375+jxsyZIiampp033336Z133mn19EeS5syZo/79+2vq1KnavHmznnrqKU2ZMkWRkZG68cYb2/YfAYARGIYAtGr69Olau3atXnnlFV188cV68cUX9dhjj/k95rbbbtNll12mvLw85eTkqH///lqwYEFA6ycnJ2vLli2qrKxUVlaWVq5cqcLCQp1++ul+j5s2bZrmz5+vZcuW6eyzz9a8efNaXa9Hjx7auXOnMjIylJubq9mzZ+uUU07Ra6+95lerB4Bvc3m9Xm+oNwEAABAqnAwBAACjMQwBAACjMQwBAACjMQwBAACjMQwBAACjMQwBAACjMQwBAACjMQwBAACjMQwBAACjMQwBAACjMQwBAACjMQwBAACj/T+IDVmvbl4nJQAAAABJRU5ErkJggg==\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 33, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 33, + "metadata": { + "inputHidden": false, + "outputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## Error Handling" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "def reciprocal(x):\n", + " time.sleep(1)\n", + " return 1/x\n", + "\n", + "with ezpq.Queue(n_workers=5, job_runner=threading.Thread) as Q:\n", + " for _ in range(20):\n", + " Q.put(reciprocal, random.randint(0, 5), suppress_errors=True)\n", + " Q.wait()\n", + " output = Q.collect()" + ], + "outputs": [], + "execution_count": 34, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "[x for x in output if x['exception'] is not None]" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 35, + "data": { + "text/plain": [ + "[{'qid': '0cb0d2fb',\n", + " 'id': 9,\n", + " 'name': 9,\n", + " 'priority': 100,\n", + " 'lane': None,\n", + " 'timeout': 0,\n", + " 'function': 'reciprocal',\n", + " 'args': [0],\n", + " 'kwargs': None,\n", + " 'submitted': datetime.datetime(2019, 3, 12, 23, 56, 34, 672407),\n", + " 'started': datetime.datetime(2019, 3, 12, 23, 56, 35, 799073),\n", + " 'ended': datetime.datetime(2019, 3, 12, 23, 56, 36, 800570),\n", + " 'processed': datetime.datetime(2019, 3, 12, 23, 56, 36, 830566),\n", + " 'exitcode': -1,\n", + " 'cancelled': False,\n", + " 'runtime': 1.0014970302581787,\n", + " 'output': None,\n", + " 'exception': 'Traceback (most recent call last):\\n File \"../ezpq/Queue.py\", line 578, in _job_wrap\\n out = _job.function(*args, **kwargs)\\n File \"\", line 3, in reciprocal\\n return 1/x\\nZeroDivisionError: division by zero\\n',\n", + " 'callback': None},\n", + " {'qid': '0cb0d2fb',\n", + " 'id': 20,\n", + " 'name': 20,\n", + " 'priority': 100,\n", + " 'lane': None,\n", + " 'timeout': 0,\n", + " 'function': 'reciprocal',\n", + " 'args': [0],\n", + " 'kwargs': None,\n", + " 'submitted': datetime.datetime(2019, 3, 12, 23, 56, 34, 672626),\n", + " 'started': datetime.datetime(2019, 3, 12, 23, 56, 37, 858694),\n", + " 'ended': datetime.datetime(2019, 3, 12, 23, 56, 38, 862628),\n", + " 'processed': datetime.datetime(2019, 3, 12, 23, 56, 38, 883271),\n", + " 'exitcode': -1,\n", + " 'cancelled': False,\n", + " 'runtime': 1.0039341449737549,\n", + " 'output': None,\n", + " 'exception': 'Traceback (most recent call last):\\n File \"../ezpq/Queue.py\", line 578, in _job_wrap\\n out = _job.function(*args, **kwargs)\\n File \"\", line 3, in reciprocal\\n return 1/x\\nZeroDivisionError: division by zero\\n',\n", + " 'callback': None}]" + ] + }, + "metadata": {} + } + ], + "execution_count": 35, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "# for x in output:\n", + "# if x['exception'] is not None:\n", + "# x['exitcode'] = 1\n", + "# else:\n", + "# x['exitcode'] = 0" + ], + "outputs": [], + "execution_count": 36, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "ezpq.Plot(output).build(color_by='exitcode', color_pal=['red', 'green'])" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "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nVnZlmq21ygcC8vva/qsCnILkpdDoZAT0dBGzJs3T4cddphmzJihzMxM7du3T0888YTuv/9+zZo1y+14SWvWrNEtt9yiN998U4FAQGeffbbmzZunrl27at68ebr++uv15ptvavDgwZKkf/3rXxo0aJCuvPJK3XnnnQ22E/Tu3VsVFRVasGCBFixYIEkqKSnRJZdcIkl64okndO+996q8vFwdO3bU8ccfr4ceeki9evWSJL3//vu69tprVVpaqkAgoBEjRuiee+5Rz549k5n//e9/a9q0aVq+fLnat2+viRMnJn9Z7uui0ahuvvlmLV++XDU1NRowYIDuvPNOjRw5Ms1/qw1RYlMUjUYVCAQ886AkefPB1rZtZmUIp2ZVVFLkYCqkU+Xk/3xEaH5+votJYJp//etfmjFjRnL7QGZmpi699FJNmDDB5WT/sWbNGp166qk666yztHjxYu3Zs0e33nqrRo8erTVr1uiqq67SH//4R02YMEFr165VMBjURRddpMMPP1wzZ8484DmXL1+us846S0VFRfrv//5vSdJhhx0mSbrrrrt0/fXX69JLL9WcOXMUi8W0atUqbdu2Tb169dKnn36qU045RYcddpieeuop1dbW6pZbbtGwYcO0bt06derUSZI0adIkrVy5Ur/61a/Up08fPfjgg/rDH/5QL0ddXZ1GjBihzz//XHPmzNEhhxyip556SmeffbbefvttDRw4MI1/sw1RYgEAgBF69+6tzZs3JwucJFVUVKh3797uhfqGG2+8Uccdd5yWLVuWfGI+cOBADRgwQM8//7zOOussPfbYYzrmmGN08803q0uXLlq7dq3Kysq+9ZWJwYMHq127durWrVu9bQY7d+7UjBkzNGXKFBUXFyePjx49Onn53nvvVSwW04svvqhwOJw8X//+/fXYY4/pyiuv1D//+U8tW7ZMv/3tbzVp0iRJ0umnn64jjjiiXo7f//73evfdd/Xee++pf//+ydt9/PHHmjVrlp555hkH/gYbjxKbouzsbEUiEU++RO2lVUvLshSPx5mVAZyaVenEUgdTNZ8XV82T2wkizdtOkJOT42AqtCVHH320Zs6cqWHDhqlLly7atm2bXn31VY0YMUIvvPBC8nZnnHGGK/n27t2r1atXa+7cuUokEsnjffv2VY8ePVRWVqazzjpLvXr10rx583TppZcqEAho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Azg1q9KJpQ6maj4vrpontxNEmredICcnx8FUaEsGDhyo4uJirV69WhUVFdq2bZsyMzM1bNgwFRUVNfg00bbC7/frjDPO0K233qoTTjjB7TgthhKbomAwqFAo5Lli5Pf7PVeMmJUZnJpVYc9CB1M1n1efcFQHq5Wbm+up+xXMctBBB+nMM890O0ar0q1bN11xxRVux2hxlFgAAGCMNWvWaOXKldq2bZu6dOmiM844QyeeeKLbsRS5/XYd+tRTjp7zWElVW7Y4ek4vocQCAAAj/PWvf9VTTz2lMWPGKC8vT1VVVVq4cKH27t2r4cOHux0PLYwSCwAAjLB8+XLddNNNOvLII5PH+vXrp/nz57epEvv73/9eU6dOlST16tVLH3zwgcuJ3NHkEvvRRx/V+9jZgoKCev+oAAAAnPTFF1806BpHHnmktm7d6lIid1x44YW68MIL3Y7hupRL7O7duzVlyhQ988wzsixL7du3V21trfx+v8477zw98sgj6tixYzqyAgCANiwcDmv79u2KRCLJY9u3b1fnzp1dTPV/OWbO1CdXX+34x8429p2Ua2trk5fr6upUW1urdu3aeeYXSw8k5V8vvfLKK7VixQo98sgj2rlzp/bu3audO3fq4Ycf1p///GddeeWV6cgJAADauClTpmjfvn31ju3bty/50npblpmZqczMTEnSoEGDlJmZqYqKCpdTpVfKK7FLly7Vr3/9a02cODF5rFOnTpo0aZJqa2t10003qaSkxNGQAAAAgwcPbnCse/fu6t69uwtpWhfbtt2O0OJSLrHt27dXnz59DnjdoYceqmAw2OxQAAAA33Tfffc16nZXXXVVmpOgNUh5O8HEiRP10EMPNWj8tm3rwQcfrLdCCwAA4JRgMKi//e1v2rdvnzp27Kh9+/Zp9erVCgaD6ty5c/I/tA2NWom95557kpcjkYjWrl2rI444Quecc466du2qrVu36rnnntP+/ft18sknpy0sAABou7744gvdeuutGjhwYPLYunXr9Oyzz7bJT6xq6xpVYq+99toDHj/Qsv6NN96o6667LqUQK1as0KpVq7Rp0yaddNJJ9f58RUWFHnjgAW3atEndunXTlClTNGjQoJTODwAAzPfBBx/olltuqXfs6KOP1pw5c1xKBDc1ajuBZVmN/i+RSKQcIhwOa/z48Ro5cmS94/F4XLNmzdLxxx+vp59+Wueff77uvPNORaPRlL8HAAAwW48ePbR06VJZliXpy36ydOlS9ejRw+VkcEOr+MSuoUOHSpI2bNigXbt2JY+///772r9/v8aNGye/36+TTz5Zzz33nFavXq2zzz7brbgAAMAF06ZN0x133KHnnntO4XBYNTU16tChQ4PVWTd89X6sH330kctJ2o4mldg9e/boscceU2lpqWpqahQOh3XyySfr4osvVlZWlmPhNm/erN69e8vv/8+C8aGHHurq+57FYjHV1dXVy2Q627YVj8dlWZZn3hTZsqwmz6qsuixNqZrPtm0lEgllZGTk/LBvAAAePUlEQVR4Z1a2pZrtNQrHwvL7UptVQW5B8nIoFHI6GoBWpnfv3nrooYf08ccf64svvlAkEtGRRx7ZKh6T+/Tp863v3oT0SLnEfvrppzr11FO1adMmDRo0SN26ddP69eu1ZMkS3XPPPXrllVccW9bft29fg1KclZV1wI+Xq6qqUlVVlSSpvLzcke9/INFoVIFAwDMFQvJmMbJtu8mzKiopSlMqOK1ycmXycn5+Yz/XBoDJMjIy1KdPH4VCIdXW1mrjxo3q3r272rVr53Y0tLCUS+w111wjSfrnP/9Z7/OL169frx//+Mf67//+bz3zzDOOhMvMzNSePXvqHduzZ0/yEym+rri4WDNnznTk+wIAgNZnz549Ki4u1t/+9jfZtq0OHTpoz5498vl8Gjp0qC6//HJHXxFORW1trWKxmOPnbdeuHa80fYuUS+xLL72k4uLiegVWko488kjNmjVLl19+uWPhevbsmdzA/dVLBRs3btQpp5zS4LZTp07VqFGjJH25EjthwgTHcnxddna2IpFIq3jpwilfbSfw0gqzZVmKx+NNmlXpxNI0pWo+L66aJ7cTRFLfTpCTk5OmVABao/nz5yuRSOjee++t96rvp59+qieffFLz58/XDTfc4Eq2LVu2aMeOHY6fNz8/X3l5eY6f1wtSLrHxePyAK6HSlyunTXl3gkQioUQikXyHg6/2MQ4cOFChUEjLli3T6NGj9eabb6qiokKFhYUNzpGXl9ciQw4GgwqFQp4rsX6/33MltqmzKuzZ8N9Xa+HVJxzVwWrl5uZ66n4FwHlvv/22HnvssQY9pEePHrrmmmt08cUXu5QMbki5xBYWFmr27NkaNmyYDj744OTxnTt3as6cOQcs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+aSmT5+ubdu26cUXX9RVV13ldjToy994TyQSsixLlmWprq5Ofr9f//znP9WpUyf17NlT7du3VzAYlN/P8za3FRcXa/369Zo9e3a91aB169Yxr1Zk9+7dKisr0wknnKD27dvrww8/1F/+8hf99Kc/ZVatTFFRkYYMGZL8+o033tArr7yiX/ziF/rkk0+YFTyLEttIU6dO1fz583XJJZcoMzNT5557Lu9M0EosXrxYixYtSn69evVqDR8+XIMHD9ZDDz2k7du3q127dhoyZIh+8pOfuJgUW7du1fPPP69gMKhJkyYlj48bN07dunVjXq3MX//6Vz388MOyLEvhcFhjxozR2Wefrddff51ZtSLt2rVTu3btkl9nZWUpIyNDnTt31rp165gVPMtn27btdggAAAAgFbymAAAAAONQYgEAAGAcSiwAAACMQ4kFAACAcSixAAAAMA4lFgAAAMahxAIAAMA4lFgAAAAYhxILoNGi0ah8Pp8ee+yxFvuer776qu64444Gx2fMmKGOHTu2WA4AQOtCiQXQqn1bib3sssv0yiuvuJAIANAaBNwOAKDt2bdvnzIzM5t1ju7du6t79+4OJQIAmIaVWADf6pFHHlHv3r3VoUMHnXbaafrkk0/qXe/z+TR37tx6x+bNmyefz5f8+tVXX5XP59Of//xnjRs3TgcddJDOO+88SdITTzyhoqIihcNhde7cWaeeeqr+/ve/J//sjBkzNHPmTO3Zs0c+n08+n0+nnnpq8rpvbieoqKjQuHHjdPDBBysrK0unn3663n///Xq36d27t6ZNm6YFCxaoV69eOvjggzVmzBht27at2X9fAICWw0osgANasWKFpkyZoksuuUTnn3++1q5dmyyfTTFlyhRNmDBBy5cvV0ZGhiRp06ZNuuiii3TYYYeprq5OTz/9tE455RStW7dOffv21WWXXabPPvtMf/jDH7Rq1SpJ0kEHHXTA8+/atUunnnqq/H6/Fi5cqPbt22vOnDnJ8/Xo0SN52z/96U/6+OOPtWDBAn3xxReaPn26rrzySi1atKjJ/38AgJZFiQVwQLNnz9bJJ5+skpISSdLpp5+u2tpazZo1q0nnGzVqlH7961/XO/aLX/wiedmyLI0YMUJ///vf9dhjj+mOO+5Ibhnw+/068cQTv/P8JSUlqqio0AcffKB+/fpJkoYNG6aePXtq3rx5uvvuu5O3tW1bf/rTn9SuXTtJX5bpO+64Q5Zlye/nBSoAMAE/rQE0kEgktHbtWo0dO7be8XHjxjX5nGeffXaDY+Xl5Ro7dqy6deumjIwMBYNBrV+/Xh999FHK53/jjTc0YMCAZIGVpHA4rBEjRqi0tLTebYcNG5YssJLUv39/xWIxbd26NeXvCwBwByuxABrYtm2b4vG4unbtWu94t27dmnzOb/7ZXbt2aeTIkerSpYvuuece9erVS+3bt9dll12m2tralM+/Y8eOA+br1q2b/vGPf9Q7lp2dXe/rUCgkSU36vgAAd1BiATTQpUsXBQKBBiuTn3/+eb2v27Vrp7q6unrHduzYccBzfv2XvSRpzZo1+uyzz7RixQoNGjQoeXznzp1NeteBcDis9evXNzj++eefKxwOp3w+AEDrxnYCAA1kZGRoyJAhWr58eb3j//M//1Pv6+7du6u8vLzesZdeeqlR32Pfvn2S/rMKKkl/+9vftGnTpnq3C4VC2r9///eer6ioSO+//369Irtjxw799a9/VVFRUaMyAQDMQYkFcEC33HKL3njjDU2cOFErV67UHXfcoSeffLLebcaNG6clS5bo/vvv18qVK/Wzn/1MlZWVjTr/iSeeqI4dO+rnP/+5XnzxRZWUlOj888/XIYccUu92/fr1Uzwe13333aeysrIDrrZK0sSJE9WrVy+dffbZWrRokZ599lmNHDlSgUBAV199ddP+EgAArRYlFsABjRo1SgsXLtTLL7+sMWPG6MUXX9TixYvr3ea2227TBRdcoJkzZ2rChAnq1auXrrrqqkadv1u3blqyZIm2bt2q0aNHa968eSouLtbhhx9e73bnnHOOrrjiCt1555064YQTNHXq1AOer1OnTnr11Vc1aNAgTZkyRRdeeKE6d+6s119/vd7bawEAvMFn27btdggAAAAgFazEAgAAwDiUWAAAABiHEgsAAADjUGIBAABgHEosAAAAjEOJBQAAgHEosQAAADAOJRYAAADGocQCAADAOJRYAAAAGIcSCwAAAONQYgEAAGCc/w+H67uPpJDX4QAAAABJRU5ErkJggg==\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 37, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 37, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Shared Objects" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "def fibonacci(shared):\n", + " shared_clone = tuple(shared)\n", + " shared[0] = shared[1]\n", + " shared[1] = sum(shared_clone)\n", + " return shared[1]" + ], + "outputs": [], + "execution_count": 38, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "import multiprocessing as mp\n", + "mgr = mp.Manager()\n", + "shared_list = mgr.list([0,1])\n", + "\n", + "with ezpq.Queue(n_workers=10) as Q:\n", + " for _ in range(20):\n", + " Q.put(fibonacci, args=shared_list)\n", + " Q.wait()\n", + " output = Q.collect()\n", + "\n", + "mgr.shutdown()\n", + " \n", + "[x['output'] for x in output]" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 39, + "data": { + "text/plain": [ + "[1,\n", + " 2,\n", + " 3,\n", + " 5,\n", + " 8,\n", + " 13,\n", + " 21,\n", + " 34,\n", + " 55,\n", + " 89,\n", + " 144,\n", + " 233,\n", + " 377,\n", + " 610,\n", + " 987,\n", + " 1597,\n", + " 2584,\n", + " 4181,\n", + " 6765,\n", + " 10946]" + ] + }, + "metadata": {} + } + ], + "execution_count": 39, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "# New in v0.2.0" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## `tqdm` Integration" + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Add `show_progress=True` to `ezpq.Queue()`; this works for `map()` and the `@decorator`" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(5, show_progress=True) as Q:\n", + " output = Q.map(time.sleep, range(5))" + ], + "outputs": [], + "execution_count": 40, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "@ezpq.Queue(n_workers=5, show_progress=True)\n", + "def time_sleep(x):\n", + " time.sleep(x)\n", + "\noutput = time_sleep(range(5))" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "cd81600d87fa4ed6aab9a529d6479101" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + } + ], + "execution_count": 41, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Or add `show_progress=True` to `ezpq.map()`" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(5) as Q:\n", + " output = Q.map(time.sleep, range(5), show_progress=True)" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "b30a962d637c4201802ad0eacaa1fc05" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + } + ], + "execution_count": 42, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Or add `show_progress=True` to `ezpq.Queue.wait()`" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(5) as Q:\n", + " for i in range(5):\n", + " Q.put(time.sleep, i)\n", + " Q.wait(show_progress=True)\n", + " output = Q.collect()" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=5), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "5a40789060c74495b10e6d26da9d6e1a" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + } + ], + "execution_count": 43, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Or just call `ezpq.Queue.waitpb()` in place of `ezpq.Queue.wait()`." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "from random import random" + ], + "outputs": [], + "execution_count": 44, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(5) as Q:\n", + " for i in range(50):\n", + " Q.put(time.sleep, random())\n", + " Q.waitpb()\n", + " output = Q.collect()" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=50), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "1c9a2e6991c34205acc58566cb6f0733" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + } + ], + "execution_count": 45, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## map" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "def my_pow(x, k):\n", + " return '{}^{} = {}'.format(x, k, x**k)\n", + "\n\n", + "with ezpq.Queue(10) as Q:\n", + " # raise all elements of `iterable` to power 2.\n", + " output = Q.map(my_pow, iterable=range(100), args=2)\n", + " \n", + "[x['output'] for x in output[:10]]" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 46, + "data": { + "text/plain": [ + "['0^2 = 0',\n", + " '1^2 = 1',\n", + " '2^2 = 4',\n", + " '3^2 = 9',\n", + " '4^2 = 16',\n", + " '5^2 = 25',\n", + " '6^2 = 36',\n", + " '7^2 = 49',\n", + " '8^2 = 64',\n", + " '9^2 = 81']" + ] + }, + "metadata": {} + } + ], + "execution_count": 46, + "metadata": { + "scrolled": true + } + }, + { + "cell_type": "markdown", + "source": [ + "## starmap\n", + "\niterate over a list of lists." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "# list of lists to iterate over.\n", + "args_list = [( x, x%4 ) # (x, k)\n", + " for x in range(100)]\n", + "\nargs_list[:10]" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 47, + "data": { + "text/plain": [ + "[(0, 0),\n", + " (1, 1),\n", + " (2, 2),\n", + " (3, 3),\n", + " (4, 0),\n", + " (5, 1),\n", + " (6, 2),\n", + " (7, 3),\n", + " (8, 0),\n", + " (9, 1)]" + ] + }, + "metadata": {} + } + ], + "execution_count": 47, + "metadata": { + "collapsed": false, + "outputHidden": false, + "inputHidden": false + } + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(10) as Q:\n", + " output = Q.starmap(my_pow, iterable=args_list)\n", + " \n", + "[x['output'] for x in output[:10]]" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 48, + "data": { + "text/plain": [ + "['0^0 = 1',\n", + " '1^1 = 1',\n", + " '2^2 = 4',\n", + " '3^3 = 27',\n", + " '4^0 = 1',\n", + " '5^1 = 5',\n", + " '6^2 = 36',\n", + " '7^3 = 343',\n", + " '8^0 = 1',\n", + " '9^1 = 9']" + ] + }, + "metadata": {} + } + ], + "execution_count": 48, + "metadata": { + "collapsed": false, + "outputHidden": false, + "inputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## starmapkw\n", + "\n`starmap`, but with a list of dicts." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "# list of dicts to iterate over.\n", + "kwargs_list = [{ 'x':x, 'k':x%4 } # (x, k)\n", + " for x in range(100)]\n", + "\nkwargs_list[:10]" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 49, + "data": { + "text/plain": [ + "[{'x': 0, 'k': 0},\n", + " {'x': 1, 'k': 1},\n", + " {'x': 2, 'k': 2},\n", + " {'x': 3, 'k': 3},\n", + " {'x': 4, 'k': 0},\n", + " {'x': 5, 'k': 1},\n", + " {'x': 6, 'k': 2},\n", + " {'x': 7, 'k': 3},\n", + " {'x': 8, 'k': 0},\n", + " {'x': 9, 'k': 1}]" + ] + }, + "metadata": {} + } + ], + "execution_count": 49, + "metadata": { + "collapsed": false, + "outputHidden": false, + "inputHidden": false + } + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(10) as Q:\n", + " output = Q.starmapkw(my_pow, iterable=kwargs_list)\n", + "\n[x['output'] for x in output[:10]]" + ], + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 50, + "data": { + "text/plain": [ + "['0^0 = 1',\n", + " '1^1 = 1',\n", + " '2^2 = 4',\n", + " '3^3 = 27',\n", + " '4^0 = 1',\n", + " '5^1 = 5',\n", + " '6^2 = 36',\n", + " '7^3 = 343',\n", + " '8^0 = 1',\n", + " '9^1 = 9']" + ] + }, + "metadata": {} + } + ], + "execution_count": 50, + "metadata": { + "collapsed": false, + "outputHidden": false, + "inputHidden": false + } + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Synchronous Lanes" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "jobs = {\n", + " 'Lane 1': [1,2,3],\n", + " 'Lane 2': [4,5,6],\n", + " 'Lane 3': [7,8,9],\n", + " 'Lane 4': [10,11,12],\n", + " 'Lane 5': [13,14,15],\n", + " 'Lane 6': [16,17,18]\n", + "}" + ], + "outputs": [], + "execution_count": 51, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(n_workers=3) as Q:\n", + " for lane in jobs.keys():\n", + " for job in jobs[lane]:\n", + " Q.put(time.sleep, args=1,\n", + " lane=lane, name='Job '+str(job))\n", + " Q.waitpb()\n", + " output = Q.collect()" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=18), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "062e5be2c86940c1b84bafedffaac745" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + } + ], + "execution_count": 52, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "ezpq.Plot(output).build(color_by='lane',\n", + " color_pal=['blue', 'red', 'green',\n", + " 'purple', 'orange', 'brown'])" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "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86T7ff/999WlS5eI660LgmyEAoGA3G43L8iV6vPFx65M06RPjkOPVFefPfJMn2eiOl5jMH7v+J/cnpmZGaNKUFfz5s1T+/btlZubq/j4eB09elS///3vlZeXpxkzZlhdXoMxatSo8OXJkydr+vTp2rx5s7p37y5J6tWrl4YNGyZJGjNmjKZMmaLCwkIZhqEVK1aoqKhISUlJkqRp06ZpzJgxJw2yn3zyiR566CH97//+bz09qhMjyAIAAFv417/+pdzc3PBSgvj4eN18880aPXq0xZU1LHPmzNHSpUu1b98+ORwOlZaWqrCwMLw9I+PHTymOzdIePnxYBQUFCoVCatu2bXj7scmIn/LPf/5TQ4YM0ZIlS5SdnR3lR/PTCLIR8vl8SktL4yPjSsc+Nmb28UeGYSgYDNInleiR6uqzR8auHxvV8WKlPmfu/X5/VMeDddq1a6ddu3apffv24du++eYbtWvXzrqiGph169Zp1qxZeu+999SlSxc5nU61aNFCpmme9HezsrLkdrtVUFBQ6yU3n3/+ua644grNnTtXI0eOrGv5ESPIRsjj8cjr9RJQKpmmKafTSUg5jmEY9Mlx6JHq6rNHsrKzojperPCGB7Vx7rnnavr06erbt6/S09N14MABrV27VgMGDNCbb74Zvt+gQYNiXtvB6dP19eTJUT9F7U8tfAkGg1W+iOV0OnXo0CG53W75/X4Fg0HNnj1bpaWltdpfRkaGBg8erEmTJunhhx+Wz+fTnj179OWXX57wOf3yyy81YMAAzZo1q8pyhljiVRYAANjCli1b1LZtW23fvl0ff/yxtm/frqysLH311Vdat25d+KepmDhxouLj48M//fv318CBAzV48GB17txZp59+ujweT5WlAiezfPlyeTwede3aVSkpKRo4cKC2bt16wvvOmTNHBQUFmjhxohITE8M/seQwazPXbDOffvqpunfvro0bN6pbt25RG9cwDO3fv18ZGRnMtFViFqU6+qQqeqQ6eqQ6+qS6ptgn+/bt01NPPaWLL75YPp+vTmMFAgGtW7dOt956a0y+0Ld9+3YVFxdHf0Y2M1OtW7eO2piNTdP4nwEAAIBGhyALAABsYfr06dVu47BbTRtBFgAA2MK5555b7bZzzjnHgkrQUNTqqAVnnHFGRGuWtm/ffsoFAQAAnMiIESOq3TZ8+HALKkFDUasg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\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 53, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 53, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "Set the lane based on an expression." + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "with ezpq.Queue(5) as Q:\n", + " for i in range(20):\n", + " Q.put(time.sleep, random(),\n", + " lane = i % 5)\n", + " \n", + " Q.waitpb()\n", + " output = Q.collect()\n", + " \n", + "ezpq.Plot(output).build(color_by='lane', theme='dark')" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=20), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "aa04c73090ab446da549715c23327b07" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "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Df3y4ntUb6mKtTsCAKAKOJ1OtW/fXlFRUcrMzNTu3burxb+bj2R11E95V1g+blzcpgrb9u/fr9LSUrVr165s229+8xslJydbfvzzoUSiRuK6QwCoea644go999xzCgoKUmZmpqKiolRYWKixY8fq4MGDdsfzmlOnTikiIqLctnr16unkyZNezUGJBAAAPmHixIl6++239dprr5VtGzp0qCZOnKihQ4famMy76tSpo7y8vHLbcnNzVbduXa/m4JpIAADgE5o2barXX3+93LZly5apadOmNiWyR8uWLeVwOPTtt9+Wbdu1a1e55W1vYCYSAAD4hJ07d6pz587atm1b2barr75aO3futDHVzxpHfqWoulurYOS4ClvCwsI0cOBATZgwQcuWLVN6err+/Oc/a8mSJVVw/HOjRAIAgGpr1KhRZT8fP35czz33nLZs2aIff/xRDRs2VHx8vD744AMbE9pj/vz5uvvuuxUTE6O6devq0Ucf9erjfSRKJAAAqMYuu+yycp/Xrl0r6efrAk+dOqW1a9cqMDDQjmi2qlevnlatWmVrBkokAACotp544gm7I+AcKJEAAMAnNGzY8Jzf/fjjj5Kk6OhoHTt2zFuR/BolEgAA+ITVq1fL4XDI4/GU2+5wONSlSxdJ0sqVK9WzZ08b0vkfSiQAAPAJXbt2veA+vXv39kISSJRIAADgI0pKSiT9vGQdGRmprKysCkvX1eEViP6CEgkAAHxCdHS0nnzySbVr106nTp1SnTp19M0332jChAm2XwcZEREhh8Nh+bjh4eGWj2kVSiQAAPAJkydP1t69e3XfffepoKBAISEhGj16tCZNmlTueZJ2uPfee209vh147SEAAPAJbdq00ezZs1VQUCBJKigo0KxZs/Qf//EfNifzT8xEAlUoKt9V6X0zQ7OrMAkA+L4DBw6oRYsW2rdvX9m2K664QgcOHLAxlf+iRBpyOp12R4APSczoXul9l7deXYVJAMD3ffXVV5ozZ44+/PBD/fjjj4qJiVHfvn21evVq3XbbbWX7JScnez3bjBkzlJaWZvm48fHxGjZsmOXjWoESCQAAfEL79u11+PBhtWrVSq1atZIkHTp0SO3bt1f79u0l/fzMSDtKpCTFxMTYcly7UCIN8egAmEiN/czuCABQY/zxj3+0OwL+DSUSqEJc5wgAqKm4OxsAAPiEOXPmVNg2a9YsG5JAokQCAAAfsXPnzgrbdu3aZUMS+82bN0//+Z//qaCgIN1xxx22ZKjUcnazZs2MnsJ+6NChiw4EAABwNq+++mqFba+99poNSezXqFEjPf7441q3bp2ysrJsyVCpEjlgwIByJfKtt95SXl6err/+ekVHR+vYsWNat26dIiIiNHDgwCoLCwAAAJU90mjXrl3Vu0TOnj277Odnn31WTZo00YcffljufY65ubm68cYbFR0dbX1KAAAAVCvGd2e/8MILWrBgQYUXgkdEROjRRx/Vvffeq0ceecSygAAAANVdxyNtdMVPTS0fd1Pc15aPaRXjG2uys7OVm5t71u9yc3N14sSJSw4FAACA6s24RPbu3VuPPPKIPv3003LbP/nkEz366KPq3bu3ZeEAAAAqq0OHDnZH8CvGJXLx4sVq1KiRevXqJZfLpVatWsnlcql3796KiYnRokWLqiInAADAeb3wwgt2R/CakpISFRYWqqSkRKWlpSosLNSZM2e8msH4msiYmBht375dH374obZt26ajR48qJiZGXbp0Ud++fasiIwAAgN544w2tWbNGa9asUU5OToXvPR6PDal+9lXjPdoaZf0zK+MUd9bt06ZN05QpU8o+r1q1SkOHDtXSpUstz3AuF/3aw759+1IaAQCA16xevVr9+/fXqFGjtGnTJqWkpGjTpk0qLS21O5rXTZ48WZMnT7Y1Q6VKZHZ2turVq6eAgABlZ1/4XcAul+uSgwEAAPy7lStXauXKlWrVqpX69++vSZMmqaSkRB988IFWr15t9GIUXLpKlcioqCht2bJFXbp0UWRk5AX/n+R2uy0JB9gpvyjK7gjGit1Byi8Kv/COlyg0KLPKjwEA57Jv3z49++yzev7559WzZ0/1799fK1euVEAAb3P2pkqVyFdeeUUtWrQo+9mfm77T6bQ7ArwkIyvR7ggXJccLLy5offnyqj8IAFxASUmJ1q1bp3Xr1ikqKkrXX3+93ZH8SqVK5NChQ8t+HjZsWFVlAQAAuCiZmZl688037Y7hVy76xhp/xVK9/4iNTLU7grG8vLwKb5MCgJqiWbNmuvvuu5Wfn6/58+frxIkTatSokTwej44ePWp3PL9DiQTOwRev+yt0Zis0qMjuGABQJaZMmaIDBw4oNDRUY8eO1YQJE9S4cWMNHTpUo0aNsjue36FEAgAAnxAbG6thw4YpNDRUK1eulCTt2LFD06dPtzmZ1LJlSwUFBVk+bp06dSwf0yqUSAAA4BOOHDkil8ulrKwshYaGSpLCwsKqxXMif//739sdweu4Fx4AAPiEDz74QNOnT1dCQoICAgKUkJCgp59+Wtu2bbM7ml+66JnI/fv3l3vt4dVXX61WrVpZmQ0AAKDMXXfdJUkaP368Tp8+rXvuuUc7d+7UwoULbU7284PQ9+7da/m43bp1U+/evS0f1wrGJfLUqVNKSkrSX/7yF5WWlio4OFiFhYUKCAjQH/7wB7300kvVev0eAAD4phtvvNHuCOd06NChKnl39/fff2/5mFYxXs6+7777lJKSopdeekm5ubnKz89Xbm6uXnzxRa1Zs0b33XdfVeQEAABANWI8E/n222/r6aef1vDhw8u21a1bVyNGjFBhYaHGjx+vJUuWWBoSAADg3XffrdRb8wYMGOCFNDAukcHBwWrWrNlZv2vevLkCAwMvORQAAMCvvfPOO7rpppv01ltv6ccff1R0dLRuv/12paSkVMn1iDg/4xI5fPhwLVy4UImJieV+G/B4PFqwYEG5GUoAAACr9O3bV2PGjCn3dppNmzbp+eef16uvvmpjMv9UqRI5a9assp8vu+wy7dixQ1deeaX69eunBg0a6Pjx43r//fdVVFSk7t27V1lYAADgv6Kjo5Wbm1tuW05OjqKjo21KZI+ioiKNGjVK69evV1ZWlmJjYzVhwgQNHjzYqzkqVSLHjh171u1z5sypsO3RRx/VuHHjjEKkpKRow4YNSktLU3x8fLk/n56errlz5yotLU3R0dFKSkpShw4djMYHAAC+b/v27Zo6daoWLlxY9ojBe++91++eE1lSUqJGjRpp/fr1atasmTZv3qybb75ZzZo1U3x8vNdyVOru7NLS0kr/x+12G4dwuVwaNGiQbrjhhnLbS0pKNHXqVHXp0kVvvvmm7rjjDs2YMUM5OTnGxwAAAL5t6tSpysvL06uvvqoNGzZo6dKlysvL09SpU+2O5lVhYWF64okn1Lx5czkcDnXr1k1du3bV559/7tUc1eK1h9dee62kn5+xdPLkybLtu3fvVlFRkQYOHKiAgAB1795d77//flnjBgAA/uPUqVOaMmWKpkyZonr16lWrSaWOZ47oCs9Plo+7SXEX3Of06dP68ssvdf/991t+/PO5qBJ5+vRpLV26VJs2bVJ2drZcLpe6d++uoUOHKiwszLJwGRkZiouLU0DAvyZMmzdvrvT0dMuOAVR3+VGVf3h/cVCp8sOr/8P+QzNP2R0BgI+6/PLL1apVKx06dKisREZGRionJ0clJSU2p/O+0tJSDRs2TFdffXWFFd2qZlwiv//+e/Xs2VNpaWnq0KGDoqOjtW/fPq1atUqzZs3Sxx9/rCZNmlgSrqCgoEIpDQsL0/Hjxyvsm5ubW3ax7b/ftWU1p9NZZWMDZ5OR2MZo/+rze/m5tV6+3e4IAHxQz549NXnyZB09elRNmjTR+PHj1bdvX11//fUqKCjQ2LFj9eWXX9od02s8Ho/uuece/eMf/1BqamqlnqFpJeMS+eCDD0qSvvvuu3Lvyt63b59uueUWPfTQQ/rLX/5iSbiQkBCdPn263LbTp08rJCSkwr4bN25USkqKJCkrK8uS4wMAgOojKSlJjz76qLZu3aprr71WkyZN0pIlSzRlyhTdcsstuu+++zR06FC7Y3qFx+PRqFGjtGvXLq1bt86WV04bl8i1a9dq8eLF5QqkJLVq1UpTp07VPffcY1m42NhYvf322yotLS1b0j58+LASEhIq7JuQkFB21/bu3buVnJxsWY5/dzE3DgGXIjZ1T6X3zcvLU3h4eBWmAQD7xMTEaOvWrZKkzz//XPXq1dOqVatUWlqq5ORk/elPf7It21eBjbW1NMrycePOsX306NHaunWr1q9fb9v/7huXyJKSkrPOBEo/zxxeTMlyu91yu91ld3gXFxcrICBA7du3V+3atZWcnKwBAwboiy++UHp6urp27VphjIiICEVEREhiJhI1i8n1g4XZOQotqtRDFwDA5xQUFCgqKkqZmZmKjo6Ww+FQ06ZNdfjwYTVp0kR5eXl2R/SK9PR0LViwQEFBQeUuIXzsscf02GOPeS2HcYns2rWrpk2bph49epSVNunnaxKffPLJsxa8C1m5cqVWrFhR9nnz5s3q1auXxowZo8cff1zz5s3TihUr1KBBA40fP1716tUzPgYAAPBtn3zyiWbOnKm1a9eqT58+eumllzR37lzt3r1bHTt2LNclarKmTZvK4/HYHcO8RD733HNKSEhQkyZN1KtXL0VHR+v48eNav369AgMD9corrxiHGDx48Dmfsh4XF6eZM2cajwkAAGqW559/XiNGjFCnTp20evVqJScn6/PPP9c111yjv/71r9q4caPdEf2KcYls166dvv76az3//PPatGmTvv32W7lcLt1999164IEH1Lhx46rICQAA/NyZM2e0ePHictu+++47fffddzYl8m8X9ZzIJk2alHufNgAAQFUbOXKk3n333bPe+xAfH6+8vDx9++23NiTzT5UqkVdddZXeeOMNtWvXTu3btz/vc4gcDodcLpe6dOmiRx55RC6Xy7KwAADAf91999266aabdM8991R4ZnRoaKj+67/+y9Y7tP1NpUpk586dyx763blz5ws+zPLkyZN6+eWXtW/fPr377ruXnhIAAPi9goICrVmzRgsXLtS9996rY8eOlX23ZcsWjR8/3sZ0/qdSJXLJkiVlPy9durRSA69evVp33XXXRYUCAAD4NYfDoZdfflnFxcVavHixRo0apR9++EGSVFRUVC3uWPYnF3VNZGX06NFDy5Ytq6rhAQCAn1q2bJnOnDmjl19+Wc8++6x27NihIUOGaPfu3bZl6tmzp9LT0y0f96qrrrJ8TKtUWYmsV6+eBgwYUFXDAwAAP/PvM40rVqxQZmamHnroIUVGRiotLa3s1cx2iI+PV3x8vG3Ht0OVlUgAAAArDRo0qNzn9evXa/369apbt65OnjxpUyr/RYkEAAA+4dd3ZP+iOhTIuXPnav/+/ZaP27179wrlubqgRAIAAJ/wm9/8RmPGjNHp06f11FNP6fvvv1fLli0VEBCgvXv32prt1KlTuuyyyywfNz8/3/IxrRJgdwAAAIDKmDBhgj7//HMdPHhQDzzwgCSpdu3aGjdunM3J/BMzkVDtKHt+y3G7SyVJTie/y1glNKhYtcOr72+tF6M4M9TuCACqiaioKL344osKDg4uew71N998o2bNmtmczD9RIg05nU67I1guMjHD7giwSKQkKcfmFNb6x/LWdkcAUE3s27dPsbGxysjIUFBQkCQpOjpaRUVFNifzT5RIAADgE3bs2KGZM2fq7bffltPp1O23365bb71VH3/8sd3R/BIl0pDb7bY7guWyUmNtOS7L2dbLy8tTeHi43TEAoEr89re/1cmTJ3XDDTfowIED6tKli95//32tWLHC7mhel5SUpDVr1ujkyZNyuVxKSkrSY4895tUMlEjYds3ZL4W8Jl4iYJf87EIFF3ENIYCa6X/+53/sjlBtjBkzRnPmzFFISIi+//57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\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 54, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 54, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + " " + ], + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Plot Facetting" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "all_output = list()\n", + "\n", + "for qid in [1, 2, 3]:\n", + " with ezpq.Queue(5, qid='queue_' + str(qid)) as Q:\n", + " for i in range(20):\n", + " lane = i % 5\n", + " Q.put(time.sleep, args=1,\n", + " lane=lane, name='Job '+str(job))\n", + " Q.waitpb()\n", + " all_output.extend( Q.collect() )" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=20), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "0ef8fe4c9f9a4a53b45d4a56166bb9ea" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=20), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "020ac7a17bbb441eacc238278285007d" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=20), HTML(value='')))" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "99151c04267f47bf9d179566af90ab4e" + } + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n" + ] + } + ], + "execution_count": 55, + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "ezpq.Plot(all_output).build(facet_by='qid',\n", + " color_by='lane',\n", + " color_pal=['blue', 'orange', 'green',\n", + " 'red', 'purple'])" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "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\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 56, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 56, + "metadata": {} + }, + { + "cell_type": "markdown", + "source": [ + "## Plot Themes & Colors" + ], + "metadata": {} + }, + { + "cell_type": "code", + "source": [ + "ezpq.Plot(all_output).build(facet_by='qid', theme='dark',\n", + " color_by='lane',\n", + " color_pal=['cyan', 'orange', 'lime',\n", + " 'red', 'yellow'])" + ], + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": [ + "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OHzevHktFtECgJWwFhHwj02bNslms8nj8TQbt9lsGjp0qCRp/fr1uv322w2kCz7Gi8jhw4dLkr744otWi0gAAABJGjFixPdec8cdd/ghCSQLFJHfZ+nSpfJ4PHI4HJo2bZoGDx5sOhIAC0hI8P951W63W5K8S2wuqq5mn0jAHxobGyVdeGQdHR2turq6Fo+uTS3jycvLU0VFhc/vO2zYMKWlpfn8vr5g6SIyKytL/fv3lyRt375dTz31lJYvX67Y2NgW17pcLrlcLklSTU2NX3MCVtWVu7MzMix0XnUO51UD/hAXF6ff/va3uvnmm3XmzBlFRkbqk08+0ZNPPmlkHeSl4uPjTUfwK0sXkd+edRw3bpzef/997dmzp9UDxouLi1VUVCRJqqur81tGAADgHzk5Odq3b59mz56t+vp6hYeHa9asWVq4cGGz/SThH5YuIi8VEhLSYjHtRSkpKRoyZIgkqby8XE6n05/RAEvqyt3ZBQX+P+bsco+zAfjHTTfdpNmzZ3sfa9fX12vJkiXavn274WTByXgR2dTUpKamJrndbrndbn311VcKCQnRiRMnVFtbq4EDB0qSduzYoQMHDmjWrFmt3sdut8tut0tiJhIIBibWIV4syrvyMgHAyg4cOKD+/fvr888/944NGDBABw4cMJgqeBkvItevX69169Z535eUlGj06NGaOHGifve736mmpkbdu3dXQkKCFixYEHTrDQC0LqHKQo01DhprAH/Yu3evli1bpnfeeUeHDx9WfHy8xo4dq02bNmnixIne64LhaeSKFSu0Zs0alZeX6x/+4R+a1VL+0qYi8rrrrmvXLuxffPFFm6+dOnWqpk6d2upny5Yta/N9ALTUlWfMMgot1FiTTWMN4A9JSUk6dOiQBg0apEGDBkm6UHMkJSUpKSlJ0oU9I4OhiLz22ms1f/58vffee8aewLapiExNTW1WRP77v/+7Tp06pTvvvNO7M/x7770nu92uyZMnd1pYAAAQvH7961+bjmAZF2dey8rKrF1ELl261Pv6//yf/6OEhAS98847zc5zdLlc+ulPf6q4uDjfpwRwRbp0Y006jTUAYFK710S+8MILWrVqVYsDwe12ux5//HE98MAD+s1vfuOzgADQGhPrEGmsAcxatmyZHnrooWZjS5YsUVZWlqFEfzUmapOSe+32+X3XfGWdpTuXavc/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\n" + ] + }, + "metadata": {} + }, + { + "output_type": "execute_result", + "execution_count": 57, + "data": { + "text/plain": [ + "" + ] + }, + "metadata": {} + } + ], + "execution_count": 57, + "metadata": {} } - ], - "source": [ - "with ezpq.Queue(5) as Q:\n", - " for i in range(20):\n", - " Q.put(time.sleep, random(),\n", - " lane = i % 5)\n", - " \n", - " Q.waitpb()\n", - " output = Q.collect()\n", - " \n", - "ezpq.Plot(output).build(color_by='lane', theme='dark')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Plot Facetting" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "821725d7a29e487a874721c49a446d6b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=20), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "6bb1082eb6bf4205848e512f9d7244f2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=20), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c3077386a89d4e6a856dd06a19ab70c6", - "version_major": 2, - "version_minor": 0 + ], + "metadata": { + "kernel_info": { + "name": "mypy36" + }, + "kernelspec": { + "name": "mypy36", + "language": "python", + "display_name": "mypy36" + }, + "language_info": { + "name": "python", + "version": "3.6.6", + "mimetype": "text/x-python", + "codemirror_mode": { + "name": "ipython", + "version": 3 }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=20), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "all_output = list()\n", - "\n", - "for qid in [1, 2, 3]:\n", - " with ezpq.Queue(5, qid='queue_' + str(qid)) as Q:\n", - " for i in range(20):\n", - " lane = i % 5\n", - " Q.put(time.sleep, args=1,\n", - " lane=lane, name='Job '+str(job))\n", - " Q.waitpb()\n", - " all_output.extend( Q.collect() )" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 52, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ezpq.Plot(all_output).build(facet_by='qid',\n", - " color_by='lane',\n", - " color_pal=['blue', 'orange', 'green',\n", - " 'red', 'purple'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Plot Themes & Colors" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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WQ8//LAaGxtbXNujR48W77t06dJip4P6+npt27ZNoaGhrb6nd+/e7fMHuIwOWUSePn1au3bt0s033+yZKgYAAPCnNWvW6N5771VeXp5n7H/+53+u6F5RUVEaOXKkcnNzW332zSYdfzJeRH755ZfKz8/XJ598ohMnTig6OloTJkzQsGHDJElVVVVavHixKisrFRcXp8zMTA0YMOBb77lr1y4lJycrMzNT8fHxPs3rdDplt9t9es9gE+x7oPkav8mrx2/Sd/g9Xr1g/z0WFxf77F4ff/yxz+51JRoaGtSlS5cWY6+99toV3evuu+/Wb3/7W91yyy0tOrZNMl5ENjc3KyoqSs8++6zi4uL0+eefa968eYqLi1OfPn2Um5urESNGKC8vT9u2bVNeXp7y8/NbTfv6My9gJfwmYSX8HoGv3XPPPVq0aJGWLFmivn376re//a2nUcZbWVlZeu211zRs2DA98sgjcjgcOnTokLZv367rr79eM2bM8HH6yzPeWBMWFqYHHnhAPXv2lM1mU//+/XXLLbfo888/V0VFhc6cOaPx48crNDRUQ4cOlcPhUGlpqenYAAAA32ru3LmaOHGi5s6dqx/96EcKCwvTiy++eEX3uu6667Rt2zb93d/9nX7xi19oxIgRmjFjhiorK/X973/fx8nbxvhM5IUaGxu1d+9ejRkzRtXV1UpMTGxx9NGNN96oqqoqgwkB4NISEqpNR1BNjcN0BCBorVixwvM6MjKy1X6Q0rmu7W97L0mPPvqoHn300RZjPXv21H/+53/6JqgPWKqIdLlcWrhwoW666SZ997vf1e7du1s994+IiFBdXV2rf9bpdMrpdEo6t0M8ECyCdd2UVWVktP4Phr/l5GSbjgAgCFimiHS73Vq2bJmOHDmiZ555RjabTeHh4Tp16lSL606dOnXRowxLSko8i3Hr6+v9khkAACBYWaKIdLvdys/P1/79+5Wbm+spEh0Oh9auXSuXy+V5pL1//36lpKS0ukdKSoqna7uiokJFRUX++wMABtHIYC0FBemmIwCAX1iiiHz55Zf1xRdf6Nlnn22xr2NSUpK6dOmioqIipaamavv27aqqqtKQIUNa3cNut3u2lWAmEoAprEcEglNeXp4qKyt9ft9BgwYpLS3N5/f1BeNFZF1dnd5++22FhoZqypQpnvHx48drwoQJmj17tpYsWaJVq1YpNjZWs2bNMra9DwAAwKX4em9qqzNeRMbGxmr9+vWX/DwxMVHPP/+8HxMBwJVLqLZAd7aD2VAA7c94EQng6tCdbS0ZF9nOw99ysunOBtD+jG82DgAAgMDDTCQQ4OjOtpaCdLqzAQQHikgA8CHWIwLwh2PHjikzM1PvvPOOunXrpieeeKLVCTftjSISAAAgwEybNk1nzpzRX/7yF1VVVemuu+5Sv3799MMf/tBvGSgiAcBHqi1wbraDfSqBDu/UqVNas2aNduzYoe7duyspKUlTp07Vb37zG4pIAG1Hd7Z1FFrg3Oxszs0GjFg3YoS2Jyf7/L6FK1a0Gtu9e7dcLpduvfVWz9jf/d3f+f20PrqzAQAAAsjJkyc9p/Sd16NHD504ccKvOZiJBAIc3dnWkc652QD8IDIyUsePH28x5nQ61a1bN7/moIgEAB9hPSIAf+jbt69sNps+++wz/e3f/q0kqby8vMXjbX+giAQAH0kIM99YU9NIIQuYkPreexr51lu+v3FiYquhiIgIjR8/Xk8//bReffVVVVVV6T//8z9V6OcTsygigQBHY411ZDjMN9bk7KaxBh1bp06dlJSUpJiYGB06dEgVFRVBuaxn6dKlmjp1quLj49WtWzc9+eSTfu3MligiAQBAgOjTp49eeOEFXXPNNTp06JBiYmLU2Nioxx9/XHv37jUdz6969OihNWvWGM1AEQkEuGD8G7hVFVTTWAO0pzlz5mjt2rV65ZVXPGOTJ0/WnDlzNHnyZIPJghNFJAD4COsRgfbVq1cvvfbaay3GXn31VaVzZr0R7BMJAAACQllZmZIv2ND7jjvuUFlZmaFEwY2ZSADwkeqEBNMR5KipMR0B8KmHH37Y87qurk4vvPCCPvroIx04cEA9e/bUoEGD9PbbbxtMGLwoIoEAR3e2dRRmZJiOoOycHNMRAJ+67rrrWrzftGmTpHMbbp88eVKbNm1SaGioiWhBjyISAABY1rx580xHaBO73S6bzebz+3bv3t3n9/QV40VkcXGxtmzZosrKSg0aNEgzZ870fPazn/1Mx44dU0jIuaWbMTExWrp0qamogCXRnW0d6QUFpiMAHVrPnj0v+dmBAwckSXFxcTp48KC/Ink89NBDfv9O04wXkVFRUZowYYLKy8svenD4rFmzWi2iBQArYj0i0L7WrVsnm80mt9vdYtxms2ngwIGSpNWrV+vOO+80kC74GC8iBw8eLEnat2/fRYtIAAAASRoyZMhlr7nrrrv8kASSBYrIy1m4cKHcbrccDocmTZqk/v37m44EwCISEnxzVrXL5ZIkz9IZb9TUsDck4C9NTU2Szj2yjo6OVn19fatH16aW+OTl5amystLn9x00aJDS0tJ8fl9fsHQRmZWVpd69e0uSNm/erGeeeUaLFy9WbGxsq2udTqecTqckqba21q85AZOCuTs7I8MCZ1XncFY14C9xcXH65S9/qVtvvVUnT55UZGSkPv30Uz399NNG1kFeKD4+3nQEv7J0EfnNWcdRo0bpgw8+0I4dOy56wHhJSYmKi4slSfX19X7LCAAA/CMnJ0e7du3S9OnT1dDQoPDwcE2bNk1z585tsZ8k/MPSReSFQkJCWi2mPS8lJUUDBgyQJFVUVKioqMif0QBjgrk7u6DAN0edXc3jbAD+c8stt2j69Omex9oNDQ1asGCBNm/ebDhZcDJeRDY3N6u5uVkul0sul0tnz55VSEiIjh49qrq6OvXt21eStGXLFu3Zs0fTpk276H3sdrvsdrskZiKBYOGr9YjnC/FgXhoABII9e/aod+/e+uKLLzxjffr00Z49ewymCl7Gi8jVq1dr1apVnvelpaUaPny4xo4dq1//+teqra1V586dlZCQoDlz5gTdegMAl5ZQbYHGGgeNNYC/7Ny5U4sWLdK7776rAwcOKD4+XiNHjtS6des0duxYz3XB8DRyyZIlWrFihSoqKvRP//RPLWopf2lTEXnDDTd4tQv7vn372nztxIkTNXHixIt+tmjRojbfBwhWwTx7llFogcaabBprAH9JSkrS/v371a9fP/Xr10/SuZojKSlJSUlJks7tGRkMReT111+v2bNn6/333zf2BLZNRWRqamqLIvK//uu/dPz4cd19992eneHff/992e12jR8/vt3CAgCA4PXzn//cdATLOD/zWl5ebu0icuHChZ7X//Ef/6GEhAS9++67Lc5zdDqd+uEPf6i4uDjfpwRwSUHdWJNOYw0AmOL1msgXX3xRy5Yta3UguN1u15NPPqmHHnpIv/jFL3wWEAAuxVfrEWmsAQLDokWL9Mgjj7QYW7BggbKysgwl+tqIqHVK7rbd5/ddcdb8sp1L8fqv3UeOHPFs6n0hp9Opo0ePXnUoAACAC5WVlbUaKy8vN5AE0hXMRN511136xS9+oYSEBA0bNswz/oc//EFPPvkkZ1YC8JtqCxx76ODYQ8BvVq5c2WrslVdeMZAE0hUUkS+//LLuvfdeDR8+XHa7XTExMTp06JCcTqe++93vKj8/vz1yAriEYH4EW2iBYw+zOfYQgAFNTU2e/7lcLjU2NqpTp04KDQ31Wwavi8j4+Hj9+c9/1rvvvqs//elPqq2tVXx8vAYOHKiRI0e2R0YAAABLe+9Iqt6q9X0dlJh48fFnn31WzzzzjOf9mjVrNHnyZK1YscLnGS7lijcbHzlyJEUjYAHB3J2dzrGHAIJUTk6OcnJ018CjAAAgAElEQVRyjGZoUxF55MgR9ejRQyEhITpy5Mhlr4+KirrqYABwOb5aj0h3NgB4r01FZExMjD766CMNHDhQ0dHRlz29JphnRgAAQPvp1auX7r77bk9Pxvvvv6+qqirTsYJSm4rI3/zmN+rdu7fntTdHIAJAe0kIM9+dXdNIdzbgLyNGjNDs2bP14Ycf6sCBA7rpppuUlpam3Nxcvffee6bjBZ02FZGTJ0/2vE5LS2uvLACuQDA/gs1wmO/OztlNdzbgLw899JBmzJihHTt2eMaSk5M1Z84cikgDWEUOAAACQmRkZKvNxXfu3KnIyEhDiYLbFXdnA7CGYF6DXFBNdzYQTNavX6+f/vSnWrFihdxut2w2m9LS0rR+/XrT0YISRSSAgOWr9Yh0ZwPWVVBQ4OnFcLvd6t+/v3784x/r0KFDiomJUbdu3fT5558bTin17dtX11xzjc/va+VZVopIAAGpOiHBZ/e60plIR02NzzIAuLiioqJvfW8V48aNMx3B7ygigQAXrLNnhRkZpiMo2/BGv0Aw2LBhg+kIuIQrLiJ3797d4tjDO+64Q/369fNlNgAAgBa+973vqV+/furatWuL8eXLlxtKdM7q1au1a9cun9/37//+73XXXXf5/L6+4HURefLkSWVmZuqNN96Qy+VSWFiYGhsbFRISovvvv1/Lly/3+vl9cXGxtmzZosrKSg0aNEgzZ870fFZVVaXFixersrJScXFxyszM1IABA7yNDXRYwdpYk15Q4LN70VgDBIasrCyNGjVK5eXlamxs9IxbYf/qffv2ye12+/y+NRZeNuN1ETl9+nQVFxdr+fLlGj9+vLp166YTJ05ozZo1evTRRzV9+nQVFnq3d1tUVJQmTJig8vJynThxwjPe1NSk3NxcjRgxQnl5edq2bZvy8vKUn5+vHj16eBsdQAfiy/WINNYAgWH06NH6yU9+or/+9a+mo0BXsE/k2rVrNX/+fKWnp6tbt26SpG7dumnKlCl67rnnrmjB6+DBg/X//t//U/fu3VuMV1RU6MyZMxo/frxCQ0M1dOhQORwOlZaWev0dAAAgsJ04cUJHjhwxHQNf8XomMiwsTDfccMNFP7vxxhsVGhp61aHOq66uVmJiYotHTDfeeCNnZAKGJCT45pjBq1FTwzGDQLB66aWX9MQTT2j58uWqr69v8dmXX35pKFXw8rqITE9P10svvaQf/OAHLdYguN1uLVu2TOnpvtn8V5IaGhoUERHRYiwiIkJ1dXWtrnU6nXI6nZKk2tpan2UArM6fj2AzMixwzGAOxwwCwWrevHmSzj3W/ubekTabTQMHDjQZLSi1qYhcsGCB5/V1112nHTt26KabbtKYMWMUGxururo6vfXWWzpz5oyGDh3qs3Dh4eE6depUi7FTp04pPDy81bUlJSUqLi6WpFZ/OwEAAIHv3nvvNR3BEs6cOaOHH35YmzdvVn19vRwOh55++mlNnDjRrznaVEQ+/vjjFx1ftGhRq7Enn3yyRXf11XA4HFq7dq1cLpfnkfb+/fuVkpLS6tqUlBRP13ZFRYVlNyMFfM2f3dkFBb570gAA3jp48KDndY8ePXTs2DGDacxpamrS9ddfr82bN+uGG25QaWmpRo8erRtuuEGDBg3yW442FZHnt79oL83NzWpubpbL5ZLL5dLZs2cVEhKipKQkdenSRUVFRUpNTdX27dtVVVWlIUOGtLqH3W6X3W6XxEwk0F5YjwjApE6dOmn69OkaO3asZ4vBoqIiLV68OKi2O4uIiPA82pfO7SU5ZMgQffjhh9YrItvb6tWrtWrVKs/70tJSDR8+XI8++qhmz56tJUuWaNWqVYqNjdWsWbPY3gcAgCCUnp6u66+/Xvfff79ef/11TZkyRVlZWXrwwQe1bNkyo9nWjVin7cnbfX7fwhWXX4t+6tQpffzxx3rkkUd8/v3f5oqKyFOnTmnFihXaunWrjhw5oqioKA0dOlSTJ09u1QjTFhMnTrzkc/zExEQ9//zzVxITgI8lVFugO9vBbCgQrEaNGqWpU6fq8OHDks4dSDJ37lytXLnSeBFpisvlUlpamu644w6NGDHCr9/tdRFZU1OjO++8U5WVlRowYIDi4uL0xRdfaM2aNVqwYIH++7//WwkJCe2RFcBF+LU728uDBNpDTjbd2UCwioqK8hSQ550+fbrVEYjBwu1261/+5V/017/+VRs3bvT7yT1ebzaelZUlSfqf//kflZWV6Z133lFZWZk+++wz2Ww2PfbYYz4PCQAAcPjwYV177bWSzh11GBcXp1mzZmnbtm2Gk/mf2+3Www8/rPLycr3zzjteHzntC17PRG7atEkvv/yy+vXr12K8X79+ys3N1b/8y7/4LByAy/Nrd7YP94EFAG9t2rRJSUlJKikpUWhoqN588029//77mj9/vuloSn0vVSPfGun7GydefHjatGnatm2bNm/e3OrEP3/xuohsamq66D6N0rl9HYOpOwoINqxHBGBSfn6+5/V9993X6tF2sKiqqtKyZct0zTXXtFhC+NRTT+mpp57yWw6vi8ghQ4bo2Wef1bBhwzxb6kjnToz55S9/edHtdwB0DNUWOPbQwTZDQFDr2rWrHA6Hunbtql69ennGy8rKDKbyr169esntdpuO4X0R+cILLyglJUUJCQkaPny44uLiVFdXp82bNys0NFS/+c1v2iMngEvwZ2NNoQWOPczm2EMgaI0cOVKzZs2Sy+VSY2OjZ9xms2nkyHZ4lIxv5XUReeutt+qTTz7Rr371K23dulWfffaZoqKiNHXqVM2YMUPf+c532iMnAAAIctOnT9fcuXP1xz/+0XQU6Ar3iUxISGhxnjYAc/y5DjmdYw8BGNSlSxd98MEHpmPgK20qIm+77Ta9/vrruvXWW5WUlPSt+xDZbDZFRUVp4MCB+sUvfqGoqCifhQVgFusRAZi0Zs0ajRs3TmvWrDEdBWpjEZmcnOw5iSY5Ofmym1meOHFCBQUF+uKLL/T73//+6lMCAICg9/3vf1/9+/fXpEmTWnVmT5kyxVCq4NWmIrLwG6dUrFixok03XrdunX7yk59cUSgA1pMQZr4zu6aRmVAgmBUVFamoqMh0DHzlitZEtsWwYcP06quvttftAXzFX93ZGQ7zndk5u+nMBoLZhg0bTEe4pDvvvFNVVVU+v+9tt93m83v6SrsVkT169FBqamp73R4AAAShlJQUjRs3Tj179lRtba3Wrl1riWabQYMGadCgQaZj+FW7FZEA/MNf3dkF1XRmAzDrnnvu0dSpU7Vy5UrNnDlTq1ev1mOPPabIyEi98847puMFHYpIAG3CekQApqWlpempp57S3r17lZWVpaKiIu3cuVN5eXnGi8jFixdr9+7dPr/v0KFDNWHCBJ/f1xcoIgEAQECIj4/X3r17W4zt379fsbGxhhJ97eTJk7ruuut8ft/Tp0/7/J6+QhEJoE2qExJMR5CjpsZ0BAAGNTY2Kjw8XA0NDZ7tBu+77z7t2bPHcLLgRBEJBDh/dWcXZmT45Xu+TXZOjukIAAwqLy9XcnKytm7dqs6dO+vNN9+UzWbTjBkzTEcLSpYvIhcuXKiSkhJ17vx11KVLlyomJsZgKgAA4A9xcXE6ePCgJGnevHme8dzcXNXV1enTTz/16/Gv+Jrli0hJSk1N1eTJk03HACzJX//nmV5Q4JfvAYBveuONNzRs2DBJ5x5nn7dp0yZTkfCVgCgiAZjHekQAJrjdbtMRLCkzM1MbNmzQiRMnFBUVpczMTD311FN+zRAQReTGjRu1ceNGRUdHa8yYMbrnnntMRwL8IiHh8kcN2u3H1b37yXbLUFPD1j4AYDWPPvqoFi1apPDwcNXU1OgHP/iB+vTp49ftgCxfRI4ZM0ZTpkxRRESEPvvsM82fP18REREaPHhwi+ucTqecTqckqba21kRUwOcyMixw1GAORw0CgNX079+/xfuQkJBW2x+1N8sXkb179/a8vu222zR69GiVlpa2KiJLSkpUXFwsSaqvr/drRgAA0D7Ob+VjdSPWrVPy9u0+v++KwktPJsyaNUsvvviiTp8+rcTERE2aNMnn3/9tLF9EXshms110fURKSooGDBggSaqoqFBRUZG/owE+V1Bw+aMGjx8/ru7du/shDQD4H2siLy0vL0//9m//po8//li///3vde211/r1+y1fRG7dulW33367wsLCtGvXLm3YsEGZmZmtrrPb7bLb7ZKYiUTH0Zb1iEeOHFFUVJQf0gCA/z3yyCOmI1iazWbTHXfcoXfffVfZ2dlasGCB377b8kVkcXGxli5dKpfLpejoaE2aNEkpKSmmYwEAAD/45JNPPK//9Kc/acmSJXrllVdaXZeZmamwsDC9+OKL/oxnGU1NTfrf//1fv36n5YvI5557znQEwJiE6jZ0Zx8/ru4n27E720F3NgBrOHv2rMaNGyebzaaVK1e2+Gzjxo1asGCBsSLyvdRUvTVypM/vm3iRsaNHj6q4uFipqamKjIzURx99pJdeeklz5szx+fd/G8sXkUAwy/iWBdX+kpNNdzYAa2hqalJmZqaWLVumzp07q+AbhyBUVVXpuuuuM5jOf2w2mwoLC/Wv//qvampq0t/8zd/oscce07Rp0/yagyISAAAEBJvNpoMHDyozM1P5+fnq1q2bFi5cKEm64YYbdPjwYcMJ/aNHjx7asmWL6RgUkYCVFaTTnQ0A553v1D58+LCmTp2qF198Ub/73e+0c+dOpaSk6LXXXjOcMLhQRAIW1pb1iHRnAwgW77zzjuf1sWPHlJ6erjFjxqh379761a9+pc2bNxtMF3woIgEAQECYP39+i/fNzc36/e9/bygNKCIBi6puw7nZknTcflwn2+nsbAfnZgMALoEiErCoQgucm53NudkAgEsIMR0AAAAAgYeZSMCi0ttwbrZEdzYAWEFaWpqcTqfP7xsTE+Pze/oKRSRgUW1dj0h3NgCYFx8fr/j4eNMx/IoiErCohLC2NdbYI4+re1j7NNbUNNJYAwC4OIpIwKIyHOYba3J201gDAG2Rl5enyspKn9930KBBSktL8/l9fYEiEgAAwAd4nA3AEgqqaawBAFgXRSRgUW1dj3jk5BFFdaGxBgDgX+wTCQAAAK8xEwlYVHVCQpuuO26362Q7Pc521NS0y30BAIGPIhKwqMKMDNMRlJ2TYzoCAOBb1NfX6+abb1afPn20bds2v343j7MBAAAC1MyZM9W/f38j381MJGBR6QUFbbqO7mwACE5//OMftWfPHmVkZOjll1/2+/dTRAIW1db1iBx7CADmjRixTsnJ231+3xUrLn7wxNmzZzVt2jT99re/1c6dO33+vW3B42wAAIAA89xzz+nuu+/WgAEDjGXokDORDQ0Nks4tNvU1p9OpM2fO+Py+waS5uVmS1KlTJ8NJOgZ+k1eP36Tv8Hu8esH+ezx9+rTCwsIUEsI816Xs3btXK1asUHl5udEcHbKIPH92ZVFRkdkgAADAazt27NDtt99uOoZlbd26VQcOHFDfvn0lnZs8a2hoUM+ePbV7926/rZO3ud1ut1++yY/q6+u1ceNGJSYmKjw83HQcAADghZtvvlldu3Y1HcMreXl57TILn5iYqLS0tBZjDQ0NcjqdnverV6/WK6+8og0bNiguLk42m83nOS6mQ85ERkdH64EHHjAdAwAAwOfCw8NbTJLZ7XaFhoaqZ8+efs3BggMAAIAAlpaW5veNxiWKSAAAAFwBikgAAAB4rUMWkadPn1ZZWZlOnz5tOgoAAECH1CEba3bt2qXk5GRlZmYqPj7ep/d2Op2y2+0+vWewCfY90HyN3+TV4zfpO/wer16w/x6Li4t9dq+PP/7YZ/dCa8aLyC+//FL5+fn65JNPdOLECUVHR2vChAkaNmyYJKmqqkqLFy9WZWWl4uLilJmZaXR39vP/cgNWwW8SVsLvEQgexovI5uZmRUVF6dlnn1VcXJw+//xzzZs3T3FxcerTp49yc3M1YsQI5eXladu2bcrLy1N+fr569OhhOjoAAIAkqUuXLu1yyk5oaKjP7+krxovIsLCwFns69u/fX7fccos+//xzNTQ06MyZMxo/frxCQkI0dOhQvfXWWyotLdXo0aMNpgYAAPjaY489ZjqC3xkvIi/U2NiovXv3asyYMaqurlZiYmKLyv7GG29UVVWVwYQAAPhfQkK16QiqqXGYjgALsVQR6XK5tHDhQt1000367ne/q927dysiIqLFNREREaqrq2v1zzqdTs8RQLW1tX7JCwBoKVibQfwhI6PQdATl5GSbjgALsUwR6Xa7tWzZMh05ckTPPPOMbDabwsPDderUqRbXnTp16qLnYZeUlHg6uurr6/2SGQAAIFhZooh0u93Kz8/X/v37lZub6ykSHQ6H1q5dK5fL5XmkvX//fqWkpLS6R0pKiqdru6KiQkVFRf77AwAAJNGd3Z4KCtJNRwBasEQR+fLLL+uLL77Qs88+q65du3rGk5KS1KVLFxUVFSk1NVXbt29XVVWVhgwZ0uoedrvdszcZM5EAgI6G9YiwGuNFZF1dnd5++22FhoZqypQpnvHx48drwoQJmj17tpYsWaJVq1YpNjZWs2bNYnsfAAAAw4wXkbGxsVq/fv0lP09MTNTzzz/vx0QAAFhPQrUFurMdzIbia8aLSABAx0F3dvvJKLRAd3Y23dn4mu+3VgcAAECHx0wkAMBn6M5uPwXpdGfDWigiAQAIAKxHhNVQRAIAEACqLXDsoYNthvANFJEAAJ+hsab9FFrg2MNsjj3EN9BYAwAAAK8xEwkA8Bkaa9pPOscewmIoIgEACACsR4TV8DgbAAAAXmMmEgAAi0sIM9+ZXdPITChaoogEAPgM3dntI8NhvjM7Z7c1OrM7deqkpKQkxcTE6NChQ6qoqGAtriEUkQAAICD06dNHL7zwgq655hodOnRIMTExamxs1OOPP669e/eajhd0KCIBAD7DjFD7KKimM1uS5syZo7Vr1+qVV17xjE2ePFlz5szR5MmTDSYLThSRAABYHOsRz+nVq5dee+21FmOvvvqq0jlX3Ai6swEAQEAoKytTcnJyi7E77rhDZWVlhhIFN2YiAQCwuOqEBNMR5KipMfK9Dz/8sOd1XV2dXnjhBX300Uc6cOCAevbsqUGDBuntt982ki3YUUQCAHyG7uz2UZiRYTqCsnNyjHzvdddd1+L9pk2bJEmRkZE6efKkNm3apNDQUBPRgp7xIrK4uFhbtmxRZWWlBg0apJkzZ3o++9nPfqZjx44pJOTcU/eYmBgtXbrUVFQAAOBn8+bNMx0Bl2C8iIyKitKECRNUXl6uEydOtPp81qxZrdY/AACsie7s9pFeUGA6giX07Nnzkp8dOHBAkhQXF6eDBw/6K1JQM15EDh48WJK0b9++ixaRAAAEO1PrEa1m3bp1stlscrvdLcZtNpsGDhwoSVq9erXuvPNOA+mCj/Ei8nIWLlwot9sth8OhSZMmqX///qYjAQCCQEKCmaMGXS6XJCkkJEQ1NWzt801Dhgy57DV33XWXH5JAsngRmZWVpd69e0uSNm/erGeeeUaLFy9WbGxsq2udTqecTqckqba21q85AQDndKTGmowMCxw1mGONowatoqmpSdK5R9bR0dGqr69v9eiaJRX+Y+ki8puzjqNGjdIHH3ygHTt26Ic//GGra0tKSlRcXCxJqq+v91tGAADgH3FxcfrlL3+pW2+9VSdPnlRkZKQ+/fRTPf3006yDNMDSReSFQkJCWq2DOC8lJUUDBgyQJFVUVKioqMif0QAA6lizQAUFZk5B+ebjbLSUk5OjXbt2afr06WpoaFB4eLimTZumuXPntthPEv5hvIhsbm5Wc3OzXC6XXC6Xzp49q5CQEB09elR1dXXq27evJGnLli3as2ePpk2bdtH72O122e12ScxEAgCunqn1iOcL8Y60NMBXbrnlFk2fPt3zWLuhoUELFizQ5s2bDScLTsaLyNWrV2vVqlWe96WlpRo+fLjGjh2rX//616qtrVXnzp2VkJCgOXPmKD4+3mBaAABgyp49e9S7d2998cUXnrE+ffpoz549BlMFL+NF5MSJEzVx4sSLfrZo0SI/pwEA4JyEagt0Zzvozv6mnTt3atGiRXr33Xd14MABxcfHa+TIkVq3bp3Gjh3ruY4lbf5hvIgEAHQcHekRbEahBbqzs+nO/qakpCTt379f/fr1U79+/SSd22c6KSlJSUlJks7tGUkR6R8UkQAAICD8/Oc/Nx0B30ARCQDwmQ7VnZ1OdzbwbSgiAQC4CFPrEenOvrRFixbpkUceaTG2YMECZWVlGUoU3PhrDgAACAhlZWWtxsrLyw0kgcRMJAAArVQbOjdb+vpxduJfEo1lsKqVK1e2GnvllVcMJIFEEQkA8KGO8gi20ALnZmdzbjYsjsfZAAAA8BozkQAAn+ko3dnphs7Nlr5+nA1YHUUkAAAXcBg6N1v6RiHeMVYGoAOjiAQA4AIJYeYba/5yNtFYBivr1auX7r77bsXExOjQoUN6//33VVVVZTpWUKKIBAD4TEdprMlwmG+sydlNY82FRowYodmzZ+vDDz/UgQMHdNNNNyktLU25ubl67733TMcLOhSRAAAgIDz00EOaMWOGduzY4RlLTk7WnDlzKCINoIgEAPhMR2msKaimscaKIiMjW20uvnPnTkVGRhpKFNwoIgEAuEBNo/nGmg6yMsCn1q9fr5/+9KdasWKF3G63bDab0tLStH79etPRghJFJAAAsKyCggLZbDZJktvtVv/+/fXjH/9Yhw4dUkxMjLp166bPP//ccMrgRBEJAMAFqhMSjH3318ce/sVYBispKir61vcwhyISAOAzHaU7uzAjw3QEZefkmI5gCRs2bDAdAZdgiSKyuLhYW7ZsUWVlpQYNGqSZM2d6PquqqtLixYtVWVmpuLg4ZWZmasCAAQbTAgAAU773ve+pX79+6tq1a4vx5cuXG0oUvCxRREZFRWnChAkqLy/XiRMnPONNTU3Kzc3ViBEjlJeXp23btikvL0/5+fnq0aOHwcQAgIvpKN3Z6QUFxr6b7uxLy8rK0qhRo1ReXq7GxkbP+Pk1k/AvSxSRgwcPliTt27evRRFZUVGhM2fOaPz48QoJCdHQoUP11ltvqbS0VKNHjzYVFwDQwTlqaox999fHHnaMpQG+NHr0aP3kJz/RX//6V9NRICnEdIBvU11drcTERIWEfB3zxhtv5HgjAACC0IkTJ3TkyBHTMfAVS8xEXkpDQ4MiIiJajEVERKiurs5QIgBAe0lIMHde9Xk1Neb2h8TlvfTSS3riiSe0fPly1dfXt/jsyy+/NJQqeFm6iAwPD9epU6dajJ06dUrh4eGtrnU6nXI6nZKk2tpav+QDALR0Nd3ZGRkWOK86h/OqrWzevHmSzj3W/ubekTabTQMHDjQZLShZuoh0OBxau3atXC6X55H2/v37lZKS0urakpISFRcXS1Krv50AAIDAd++995qOgG+wRBHZ3Nys5uZmuVwuuVwunT17ViEhIUpKSlKXLl1UVFSk1NRUbd++XVVVVRoyZEire6SkpHi2/qmoqGAzUgAw4Gq6swsKzJ1XjcBw8OBBz+sePXro2LFjBtPAEkXk6tWrtWrVKs/70tJSDR8+XI8++qhmz56tJUuWaNWqVYqNjdWsWbMuur2P3W6X3W6XxEwkAAQi1iPicjp16qTp06dr7NixCgsLU2Njo4qKirR48eIOs71UILFEETlx4kRNnDjxop8lJibq+eef93MiAIA/JVRboKnGQRFrdenp6br++ut1//336/XXX9eUKVOUlZWlBx98UMuWLTMdL+hYoogEAHQMV9pYk1FogaaabJpqrG7UqFGaOnWqDh8+LOncqXZz587VypUrKSINsPQ+kQAAAOdFRUV5CsjzTp8+3eoIRPgHM5EAAJ+50nVpBek01eDyDh8+rGuvvVZHjx6VzWZTXFycHnzwQW3bts10tKBEEQkAMI71iGiLTZs2KSkpSSUlJQoNDdWbb76p999/X/PnzzcdLShRRAIAgICQn5/veX3fffe1erQN/6KIBAAYV22BIw8dbDEUELp27SqHw6GuXbuqV69envGysjKDqYITRSQAwGeutDu70AJHHmZz5KHljRw5UrNmzZLL5VJjY6Nn3GazaeTIkQaTBSeKSAAAEBCmT5+uuXPn6o9//KPpKBBFJADAh660OzudIw/RBl26dNEHH3xgOga+QhEJADCO9YhoizVr1mjcuHFas2aN6SgQRSQAAAgQ3//+99W/f39NmjSpVWf2lClTDKUKXhSRAADjEsLMd2fXNDIbanVFRUUqKioyHQNfoYgEAPjMFZ+d7TDfnZ2zm+5sq9uwYYPpCPgGikgAABAwUlJSNG7cOPXs2VO1tbVau3YtzTaGUEQCAHzmis/OrqY7G5d3zz33aOrUqVq5cqVmzpyp1atX67HHHlNkZKTeeecd0/GCDkUkAMA41iOiLdLS0vTUU09p7969ysrKUlFRkXbu3Km8vDyKSAMoIgEARlUnJJiOIEdNjekIaIP4+Hjt3bu3xdj+/fsVGxtrKFFwo4gEAPjMlTTWFGZktEMS72Tn5JiOgDZobGxUeHi4GhoaZLPZJEn33Xef9uzZYzhZcKKIBAAAAaG8vFzJycnaunWrOnfurDfffFM2m00zZswwHS0oWb6IXLhwoUpKStS589dRly5dqpiYGIOpAAAXcyWNNekFBe2QBB1FXFycDh48KEmaN2+eZzw3N1d1dXX69NNPr7ihC1fH8kWkJKWmpmry5MmmYwAA2gHrEfFt3njjDQ0bNkzSucfZ523atMlUJHwlxHQAAACAS3G73aYj4BICYiZy48aN2rhxo6KjozVmzBjdc889piMBQEBLSGifYwbt9uPq3v1km66tqWFbHyCQWb6IHDNmjKZMmaKIiAh99p14tkYAAA11SURBVNlnmj9/viIiIjR48OAW1zmdTjmdTklSbW2tiagAEDAyMixwzGAOxwwCgczyRWTv3r09r2+77TaNHj1apaWlrYrIkpISFRcXS5Lq6+v9mhEAALSP81v5wHosX0ReyGazXXR9REpKigYMGCBJqqioUFFRkb+jAUDAKChon2MGjx8/ru7du7fLvRGcWBNpXZYvIrdu3arbb79dYWFh2rVrlzZs2KDMzMxW19ntdtntdknMRALA5bTXesQjR44oKiqqXe6N4PTII4+YjoBLsHwRWVxcrKVLl8rlcik6OlqTJk1SSkqK6VgAAMAPPvnkE8/rF154QR9++KHWrl3b6rq/+Zu/0ahRo7R8+XJ/xgtqli8in3vuOdMRAKDDSahup+7s48fV/WQbu7MddGfDO7feequeeeaZFmPjxo3T2rVrdfjwYY0ZM4Yi0o8sX0QCAHwvo9AC3dnZdGfDO9dcc42OHz/eYmz69Olau3atGhsbWY/rZ2w2DgAAAsLRo0fVp08fz/tevXqpa9eustvt6t69u062cRYcvsFMJAAEoYJ0urMReDZt2qTnnntOK1euVFNTk2644QYdO3ZM//Zv/6aQkBCOQvQzikgACELttR6R7my0p5dfflmdO3fWj370I/3lL39RXl6eNm3apPHjx6umpkavv/666YhBhSISAIJQdTsde3jcflwn23jsoYNjD+Gl5uZmvfjiiy3Gjh49qry8PEOJghtFJAAEoUILHHuYzbGHQECjsQYAAABeYyYSAIJQOsceArhKFJEAEITaaz0ijTVA8OBxNgAAALzGTCQABJmEsPbpzJYke+RxdQ+7fHd2TSOd2UCgo4gEgCCT4TDfmZ2zm85sINDxOBsAAABeYyYSAIJMQXX7dGZLdGcDwYQiEgCCTHuuRzxy8oiiutCdDQQDHmcDAADAa8xEAkCQqU5IaLd7H7fbdbINj7MdNTXtlgGAf1BEAkCQKczIMB1B2Tk5piMAuEo8zgYAAIDXmIkEgCCTXlDQbvemOxsIHhSRABBk2nM9ImdnA8GDx9kAAADwWoeciWxoaJAk1dfX+/zeTqdTZ86c8fl9g0lzc7MkqVOnToaTdAz8Jq8ev0nf4fd49YL993j69GmFhYUpJIR5LqvrkEVkZWWlJKmoqMhsEAAA4LUdO3bo9ttvNx0Dl2Fzu91u0yF8rb6+Xhs3blRiYqLCw8N9dt/a2lr95je/0ZQpUxQfH++z+wJXit8krITfI3zl5ptvVteuXU3HwGV0yJnI6OhoPfDAAz6/b3V1taKjo5WUlCSHo/2ODQPait8krITfIxBcWHAAAAAAr1FEesFut+sf//EfZbfbTUcBJPGbhLXwewSCS4dcEwkAAID2xUwkAAAAvEYRCQAAAK91yO7s9nDy5EktXbpUZWVlCg8P1z/90z8pNTXVdCwEiYULF6qkpESdO3/9r+zSpUsVExNjMBWCSXFxsbZs2aLKykoNGjRIM2fO9HxWVVWlxYsXq7KyUnFxccrMzNSAAQMMpgXgDxSRbfTyyy/ryy+/VGFhoerq6jRnzhx95zvfUXJysuloCBKpqamaPHmy6RgIUlFRUZowYYLKy8t14sQJz3hTU5Nyc3M1YsQI5eXladu2bcrLy1N+fr569OhhMDGA9kYR2QaNjY0qLS3Vr371K3Xt2lWJiYkaMWKENm3aRBEJ49xut1asWKEtW7bo7NmzioqK0kMPPaSkpCTT0dCBDB48WJK0b9++FkVkRUWFzpw5o/HjxyskJERDhw7V/2/vTmNj2v84jr+nM9oylE5Q0TK1RFJr4omGoiFFNLWlRGxRqUoswTNiiQZFLKktIUJLEypExfKgtZUWCRGxqyU6QqItSuhi2k7vA7nzv+e2/Of0lvn/bz+vR3O+85vf+c5kMvnkd+acc/bsWa5fv058fDzv3r1j9+7dvHz5EqvVSrdu3di8ebO/3oaINCOFSB+8ffuW+vp6nE6nt9ajRw9u3rzpx66kpcnNzSU3N5eOHTuSkJBAXFwcAHfv3qWgoICdO3ficDh49+6dnzuVluT169dERkYa7nPcs2dPXC4XAFlZWYSHh5OamgpAUVGRX/oUkeanEOmD6urqBrdfstvtVFVV+akjaWkSEhKYN28edrudR48esWXLFux2O0OHDsVms+F2u3n9+jUhISF06dLF3+1KC1JVVYXdbjfU7HY7paWlANhsNj5+/EhpaSldu3alX79+/mhTRH4BnZ3tg+Dg4AaBsbKyslnvyy3yM7169SIkJASr1crAgQOJj4/n+vXrAAwcOJAZM2aQlZXF7Nmz2bp1Kx8+fPBzx9JStG7dmoqKCkOtoqLC+/uYlJSEw+Fg9erVzJ8/n5MnT/qjTRH5BRQifRAeHg58P2zzp1evXunesOI3FouFv94nYPz48Wzfvp0DBw5QV1fH4cOH/didtCTdu3fH5XLh8Xi8tVevXnn//tOhQwcWLlzIoUOHWLlyJTk5Ody7d89f7YpIM1KI9EFwcDDDhg0jKyuLyspKXC4XeXl53v+kifxqhYWFVFZW4vF4ePz4MefPnyc6OhqA58+f8/TpU2pqaggKCiIoKMjw/zSR5lBXV4fb7cbj8eDxeHC73dTW1jJgwAACAwM5deoUNTU1FBYW4nK5GDZsGPD9u1tWVgZ8P8wdEBCg76fIv4Rue+ijr1+/smfPHu91IqdMmaLrRMpvs2LFCu9qz58n1owbNw6Ae/fucfDgQUpKSrDZbERFRbFo0SJCQ0P93LX8mxw9epTs7GxDbdSoUSxbtozi4mL27NlDcXExnTt3ZsGCBd7rRGZmZnL16lW+fv1Ku3btGDduHNOmTfPHWxCRZqYQKSIiIiKm6ZiCiIiIiJimECkiIiIipilEioiIiIhpCpEiIiIiYppCpIiIiIiYphApIiIiIqYpRIqIiIiIaQqRIiIiImKaQqSI+OzTp09YLBYyMzN/2z7z8/NJS0trUF+3bh1t27b9bX2IiIiRQqSI/E/7UYhMTk7mypUrfuhIREQAbP5uQERanqqqKlq3bv2P5oiIiCAiIqKZOhIREbO0EikiP3TgwAEiIyNp06YNo0eP5sWLF4bnLRYL27ZtM9TS09OxWCze7fz8fCwWC+fPnycxMZGQkBCmTp0KwJEjR4iJicHhcBAaGkpsbCy3bt3yvnbdunWkpqZSUVGBxWLBYrEQGxvrfe7vh7NdLheJiYm0b98eu93O2LFjefDggWFMZGQkixcvZu/evTidTtq3b8+kSZMoKyv7x5+XiEhLopVIEWnUuXPnSElJYe7cuUyfPp07d+54w19TpKSkMGvWLHJycrBarQAUFxczZ84cevXqhdvt5tixY4wYMYL79+/Tp08fkpOTefPmDUePHuXy5csAhISENDr/ly9fiI2NJSAggH379hEcHMzGjRu983Xr1s079syZMzx//py9e/fy/v17li9fzpIlS8jOzm7y+xMRaWkUIkWkURs2bGD48OFkZGQAMHbsWKqrq1m/fn2T5pswYQJbtmwx1NauXet97PF4iIuL49atW2RmZpKWluY9ZB0QEEB0dPRP58/IyMDlcvHo0SOioqIAGDlyJN27dyc9PZ3t27d7x9bX13PmzBmCgoKA72E2LS0Nj8dDQIAO0IiI+EK/liLSQF1dHXfu3GHy5MmGemJiYpPnjI+Pb1B78uQJkydPJiwsDKvVSqtWrSgqKuLZs2em5y8oKKB///7eAAngcDiIi4ujsLDQMHbkyJHeAAnQt29fampqKC0tNb1fEZGWSiuRItJAWVkZtbW1dO7c2VAPCwtr8px/f+2XL18YM2YMnTp1YseOHTidToKDg0lOTqa6utr0/OXl5Y32FxYWxsOHDw21Dh06GLYDAwMBmrRfEZGWSiFSRBro1KkTNputwcpcSUmJYTsoKAi3222olZeXNzrnX0+2Abh58yZv3rzh3LlzDBo0yFv//Plzk866djgcFBUVNaiXlJTgcDhMzyciIj+nw9ki0oDVamXw4MHk5OQY6idPnjRsR0RE8OTJE0PtwoULPu2jqqoK+M8qIMCNGzcoLi42jAsMDOTbt2//db6YmBgePHhgCJLl5eVcvHiRmJgYn3oSERHfKUSKSKNWrVpFQUEBSUlJ5ObmkpaWRlZWlmFMYmIiJ06cYNeuXeTm5jJ79mzevn3r0/zR0dG0bduWRYsWkZeXR0ZGBtOnTyc8PNwwLioqitraWnbu3Mnt27cbXW0ESEpKwul0Eh8fT3Z2NqdPn2bMmDHYbDaWLVvWtA9BRER+SCFSRBo1YcIE9u3bx6VLl5g0aRJ5eXkcP37cMGbNmjXMmDGD1NRUZs2ahdPpZOnSpT7NHxYWxokTJygtLWXixImkp6ezf/9+evfubRiXkJDAwoUL2bRpE0OGDGHBggWNzteuXTvy8/MZNGgQKSkpzJw5k9DQUK5du2a4vI+IiDQPS319fb2/mxARERGR/y9aiRQRERER0xQiRURERMQ0hUgRERERMU0hUkRERERMU4gUEREREdMUIkVERETENIVIERERETFNIVJERERETFOIFBERERHTFCJFRERExDSFSBERERExTSFSREREREz7A1uAHOzQtcWuAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 53, - "metadata": {}, - "output_type": "execute_result" + "pygments_lexer": "ipython3", + "nbconvert_exporter": "python", + "file_extension": ".py" + }, + "nteract": { + "version": "0.12.3" } - ], - "source": [ - "ezpq.Plot(all_output).build(facet_by='qid', theme='dark',\n", - " color_by='lane',\n", - " color_pal=['cyan', 'orange', 'lime',\n", - " 'red', 'yellow'])" - ] - } - ], - "metadata": { - "kernel_info": { - "name": "mypy36" - }, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.7" }, - "nteract": { - "version": "0.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file diff --git a/ezpq/Queue.py b/ezpq/Queue.py index 7d60796..4d84fdd 100644 --- a/ezpq/Queue.py +++ b/ezpq/Queue.py @@ -685,6 +685,40 @@ def map(self, function, iterable, args=None, kwargs=None, timeout=0, show_progre return self.collect() + def starmap(self, function, iterable, args=None, kwargs=None, timeout=0, show_progress=False): + + assert hasattr(iterable, '__iter__') + + if args is None: + args = [] + elif not isinstance(args, list): + args = list(args) + + for x in iterable: + job = ezpq.Job(function=function, args=list(x) + args, kwargs=kwargs, timeout=timeout) + self.submit(job) + + self.wait(show_progress=show_progress) + + return self.collect() + + def starmapkw(self, function, iterable, args=None, kwargs=None, timeout=0, show_progress=False): + + assert hasattr(iterable, '__iter__') + + if kwargs is None: + kwargs = {} + elif not isinstance(kwargs, dict): + kwargs = dict(kwargs) + + for x in iterable: + job = ezpq.Job(function=function, args=args, kwargs={**x, **kwargs}, timeout=timeout) + self.submit(job) + + self.wait(show_progress=show_progress) + + return self.collect() + def get(self, wait=False, poll=0, timeout=0): """Pops the highest priority item from the completed queue. diff --git a/ezpq/__init__.py b/ezpq/__init__.py index 9accef2..0796f9d 100644 --- a/ezpq/__init__.py +++ b/ezpq/__init__.py @@ -1,5 +1,5 @@ -__version__ = "0.2.1" +__version__ = "0.2.2" from .Job import Job from .Queue import Queue -from .Plot import Plot \ No newline at end of file +from .Plot import Plot diff --git a/setup.py b/setup.py index 2bfa21c..a112649 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ setup( name="ezpq", - version="0.2.1", + version="0.2.2", #download_url = 'https://github.com/dm3ll3n/ezpq/releases/download/0.2.0/ezpq-0.2.0.tar.gz', description="an easy parallel queueing system", long_description=README, diff --git a/test/test_processes.py b/test/test_processes.py index 87f35fb..e305507 100644 --- a/test/test_processes.py +++ b/test/test_processes.py @@ -22,11 +22,11 @@ def setUp(self): def test_priority(self): self.Q._stop() - + for i,x in enumerate(self.input): self.Q.put(function=return_me, args=x, priority=-i) # should result in reversed inputs. - + self.Q.start() self.Q.wait() @@ -34,13 +34,27 @@ def test_priority(self): self.assertEqual(tuple(reversed(self.input)), out_list) - def test_map(self): + def test_map(self): job_data = self.Q.map(function=return_me, iterable=self.input) out_list = tuple(job['output'] for job in job_data) self.assertEqual(self.input, out_list) + def test_starmap(self): + job_data = self.Q.starmap(function=return_me, iterable=[[x] for x in self.input]) + + out_list = tuple(job['output'] for job in job_data) + + self.assertEqual(self.input, out_list) + + def test_starmapkw(self): + job_data = self.Q.starmapkw(function=return_me, iterable=[{'x': x} for x in self.input]) + + out_list = tuple(job['output'] for job in job_data) + + self.assertEqual(self.input, out_list) + def test_lanes(self): for i, x in enumerate(self.input): self.Q.put(function=return_me, args=x, diff --git a/test/test_threads.py b/test/test_threads.py index a0839ed..b729e67 100644 --- a/test/test_threads.py +++ b/test/test_threads.py @@ -22,11 +22,11 @@ def setUp(self): def test_priority(self): self.Q._stop() - + for i,x in enumerate(self.input): self.Q.put(function=return_me, args=x, priority=-i) # should result in reversed inputs. - + self.Q.start() self.Q.wait() @@ -34,13 +34,27 @@ def test_priority(self): self.assertEqual(tuple(reversed(self.input)), out_list) - def test_map(self): + def test_map(self): job_data = self.Q.map(function=return_me, iterable=self.input) out_list = tuple(job['output'] for job in job_data) self.assertEqual(self.input, out_list) + def test_starmap(self): + job_data = self.Q.starmap(function=return_me, iterable=[[x] for x in self.input]) + + out_list = tuple(job['output'] for job in job_data) + + self.assertEqual(self.input, out_list) + + def test_starmapkw(self): + job_data = self.Q.starmapkw(function=return_me, iterable=[{'x': x} for x in self.input]) + + out_list = tuple(job['output'] for job in job_data) + + self.assertEqual(self.input, out_list) + def test_lanes(self): for i, x in enumerate(self.input): self.Q.put(function=return_me, args=x,