-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
169 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import multiprocessing | ||
from typing import Any, Callable, Dict | ||
|
||
class ProcessManager(object): | ||
def __init__(self, func: Callable, kill_previous: Any = False, concurrent_running: Any = False) -> None: | ||
"""ProcessManager initializer | ||
Args: | ||
func (Callable): function to be executed | ||
kill_previous (Any, optional): Do you want to kill previous process? if not, new process won't be executed if concurrent is set to False. | ||
If True, it will kill the unfinished previous process and start the new one. | ||
Defaults to False. | ||
concurrent_running (Any, optional): If True, all the process of the function will run concurrently. Defaults to False. | ||
Raises: | ||
ValueError: kill_previous and concurrent_running can't be used together. If you kill previous, what do you wanna run concurrently? | ||
""" | ||
if concurrent_running and kill_previous: | ||
raise ValueError("Using kill_previous is not allowed while using concurrent_running.") | ||
self.func = func | ||
self.kill_previous = kill_previous | ||
self.concurrent_running = concurrent_running | ||
|
||
""" | ||
We really don't need to keep track of multiple process. We will need that only when concurrent_running is true | ||
and we don't need to terminate any process. So, no use of the process ids. | ||
In the future, all the process management will be added if needed. | ||
""" | ||
self.process = None | ||
|
||
def run(self, kwargs: Dict = None) -> None: | ||
""" create a new process of the function | ||
Args: | ||
kwargs (Dict, optional): arguments to be passed to your function. Defaults to None. | ||
""" | ||
if self.concurrent_running == False and self.process is not None and self.process.is_alive(): | ||
if self.kill_previous: | ||
self.kill() | ||
else: | ||
return | ||
|
||
if kwargs == None: | ||
self.process = multiprocessing.Process(target=self.func) | ||
else: | ||
self.process = multiprocessing.Process(target=self.func, kwargs=kwargs) | ||
self.process.daemon = True | ||
self.process.start() | ||
|
||
def kill(self) -> None: | ||
"""terminate the currently running process | ||
""" | ||
if self.process is not None and self.process.is_alive: | ||
self.process.terminate() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .PManager import ProcessManager | ||
|
||
__all__ = ["ProcessManager"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
[tool.poetry] | ||
name = "processpy" | ||
version = "0.1.0" | ||
description = "Python Process Manager" | ||
authors = [ | ||
"Nazmul Hasan <[email protected]>" | ||
] | ||
|
||
license = "MIT" | ||
readme = "README.md" | ||
repository = "https://github.com/nazmulnnb/processpy" | ||
|
||
classifiers = [ | ||
'Operating System :: OS Independent', | ||
'Programming Language :: Python', | ||
'Programming Language :: Python :: 3', | ||
'Programming Language :: Python :: 3.6', | ||
'Programming Language :: Python :: 3.7', | ||
'Programming Language :: Python :: 3.8', | ||
'Programming Language :: Python :: 3.9', | ||
'Programming Language :: Python :: 3 :: Only', | ||
] | ||
|
||
[tool.poetry.dependencies] | ||
python = "^3.6" | ||
|
||
[tool.poetry.dev-dependencies] | ||
pytest = "^7.1" | ||
|
||
[build-system] | ||
requires = ["poetry-core>=1.0.0"] | ||
build-backend = "poetry.core.masonry.api" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# Python Process Manager (processpy) | ||
|
||
|
||
processpy is simple process manager for python. | ||
If you want to run multiple process for the same function, this tool is for you. | ||
|
||
* You can run multiple process of the same function concurrently. | ||
* You can choose to kill previous running process before running a new process of the same function. | ||
* You can choose to ignore new process of the same function if it's already running. | ||
|
||
|
||
## Installation | ||
|
||
```bash | ||
pip install processpy | ||
``` | ||
|
||
## Example (No concurrency and no previous kill) | ||
|
||
```python | ||
from processpy import ProcessManager | ||
import time | ||
|
||
def sum(a, b): | ||
time.sleep(30) | ||
print(a+b) | ||
|
||
sum_process = ProcessManager(sum, kill_previous=False, concurrent_running=False) | ||
sum_process.run({'a': 10, 'b': 20}) | ||
time.sleep(5) | ||
|
||
""" | ||
The following will not run. Because concurrent run is false and kill previous is also false. So, it will simply return with doing nothing and let the previous run. | ||
""" | ||
sum_process.run({'a': 10, 'b': 20}) | ||
|
||
``` | ||
|
||
## Example (No concurrency but with previous kill) | ||
```python | ||
from processpy import ProcessManager | ||
import time | ||
|
||
def sum(a, b): | ||
time.sleep(30) | ||
print(a+b) | ||
|
||
sum_process = ProcessManager(sum, kill_previous=True, concurrent_running=False) | ||
sum_process.run({'a': 10, 'b': 20}) | ||
time.sleep(5) | ||
|
||
""" | ||
The following will kill the previous unfinished process and run. Because concurrent run is false and kill previous is True. So, it will simply kill the previous unfinished process. If previous one is already finished, nothing to kill. | ||
""" | ||
sum_process.run({'a': 10, 'b': 20}) | ||
``` | ||
|
||
## Example (with concurrency) | ||
```python | ||
from processpy import ProcessManager | ||
import time | ||
|
||
def sum(a, b): | ||
time.sleep(30) | ||
print(a+b) | ||
|
||
sum_process = ProcessManager(sum, concurrent_running=True) | ||
sum_process.run({'a': 10, 'b': 20}) | ||
time.sleep(5) | ||
|
||
""" | ||
The following will run alongside of the previous process. | ||
""" | ||
sum_process.run({'a': 10, 'b': 20}) | ||
``` | ||
|
||
## You can also kill the running process (if concurrent_running=False ) | ||
```python | ||
sub_process.kill() | ||
``` |