PyChannel 0.1.3__tar.gz → 1.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyChannel
3
- Version: 0.1.3
3
+ Version: 1.5
4
4
  Summary: A Python concurrency library inspired by Go's goroutines and channels
5
5
  Author: Brayan
6
6
  Keywords: concurrency,channels,goroutines,parallelism,multiprocessing
@@ -24,8 +24,8 @@ Requires-Dist: twine>=6.1; extra == "dev"
24
24
 
25
25
  # PyChannel
26
26
 
27
- ![Python](https://img.shields.io/badge/Python-3.10%20%7C%203.11%20%7C%203.12-3776AB?style=for-the-badge&logo=python&logoColor=white)
28
- ![Versão](https://img.shields.io/badge/vers%C3%A3o-0.1.0-2ea44f?style=for-the-badge)
27
+ ![Python](https://img.shields.io/badge/Python-3.10%20a%203.14-3776AB?style=for-the-badge&logo=python&logoColor=white)
28
+ ![Versão](https://img.shields.io/badge/vers%C3%A3o-3.15-2ea44f?style=for-the-badge)
29
29
  ![Status](https://img.shields.io/badge/status-alpha-orange?style=for-the-badge)
30
30
  ![Concorrência](https://img.shields.io/badge/concorr%C3%AAncia-loky-6f42c1?style=for-the-badge)
31
31
 
@@ -110,6 +110,8 @@ resultado = channel.get() # 100
110
110
 
111
111
  Se a função gerar uma exceção, ela permanece armazenada no `Future`. Quando existe um Channel, o objeto da exceção também é enviado para ele.
112
112
 
113
+ Os executores registrados pela `Task` são finalizados automaticamente quando o programa termina. Quando for necessário encerrar o pool antes do fim do programa, use `task.shutdown()`.
114
+
113
115
  ## `Channel`
114
116
 
115
117
  O `Channel` transporta valores entre produtores e consumidores por meio de uma `multiprocessing.Queue`.
@@ -2,6 +2,6 @@ from .task import Task
2
2
  from .channel import Channel
3
3
  from .buffer import Buffer
4
4
 
5
- __version__ = "0.1.0"
5
+ __version__ = "3.15"
6
6
 
7
7
  __all__ = ["Task", "Channel", "Buffer", "__version__"]
@@ -1,4 +1,6 @@
1
- import logging
1
+ import atexit
2
+ import logging
3
+ from threading import Lock
2
4
  from concurrent.futures import Future
3
5
  from functools import wraps
4
6
  from typing import Any
@@ -10,7 +12,44 @@ from PyChannel.buffer import Buffer
10
12
  from PyChannel.channel import Channel
11
13
 
12
14
  #Pega a configuração de logs
13
- logger = logging.getLogger(__name__)
15
+ logger = logging.getLogger(__name__)
16
+
17
+ _executors = []
18
+ _executors_lock = Lock()
19
+ _cleanup_registered = False
20
+
21
+
22
+ def _shutdown_executors() -> None:
23
+ """Finaliza executores e o ResourceTracker do loky ao encerrar o Python."""
24
+ with _executors_lock:
25
+ executors = _executors.copy()
26
+
27
+ for executor in executors:
28
+ try:
29
+ executor.shutdown(wait=True)
30
+ except Exception:
31
+ pass
32
+
33
+ # O loky 3.5.6 pode deixar o ResourceTracker para o destrutor do Python,
34
+ # que falha em algumas versões recentes do Python no Windows.
35
+ try:
36
+ from loky.backend import resource_tracker
37
+
38
+ resource_tracker._resource_tracker._stop()
39
+ except Exception:
40
+ pass
41
+
42
+
43
+ def _register_executor(executor) -> None:
44
+ global _cleanup_registered
45
+
46
+ with _executors_lock:
47
+ if not any(registered is executor for registered in _executors):
48
+ _executors.append(executor)
49
+
50
+ if not _cleanup_registered:
51
+ atexit.register(_shutdown_executors)
52
+ _cleanup_registered = True
14
53
 
15
54
  #Cria tasks
16
55
  class Task:
@@ -22,9 +61,10 @@ class Task:
22
61
  buffer: Buffer = None,
23
62
  ) -> None:
24
63
  self.name = name if name is not None else "task"
25
- self.ch = channel
26
- self.buff = buffer
27
- self.process = get_reusable_executor(max_workers=max_workers)
64
+ self.ch = channel
65
+ self.buff = buffer
66
+ self.process = get_reusable_executor(max_workers=max_workers)
67
+ _register_executor(self.process)
28
68
 
29
69
  def _finished(self, future: Future[Any]) -> None:
30
70
  try:
@@ -51,7 +91,7 @@ class Task:
51
91
  if self.ch is not None:
52
92
  self.ch.send(result=output)
53
93
 
54
- def run(self):
94
+ def run(self):
55
95
  logger.info(f"Starting {self.name}...")
56
96
 
57
97
  def decorator(func):
@@ -66,4 +106,8 @@ class Task:
66
106
 
67
107
  return wrapper
68
108
 
69
- return decorator
109
+ return decorator
110
+
111
+ def shutdown(self, wait: bool = True) -> None:
112
+ """Finaliza o executor manualmente quando necessário."""
113
+ self.process.shutdown(wait=wait)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyChannel
3
- Version: 0.1.3
3
+ Version: 1.5
4
4
  Summary: A Python concurrency library inspired by Go's goroutines and channels
5
5
  Author: Brayan
6
6
  Keywords: concurrency,channels,goroutines,parallelism,multiprocessing
@@ -24,8 +24,8 @@ Requires-Dist: twine>=6.1; extra == "dev"
24
24
 
25
25
  # PyChannel
26
26
 
27
- ![Python](https://img.shields.io/badge/Python-3.10%20%7C%203.11%20%7C%203.12-3776AB?style=for-the-badge&logo=python&logoColor=white)
28
- ![Versão](https://img.shields.io/badge/vers%C3%A3o-0.1.0-2ea44f?style=for-the-badge)
27
+ ![Python](https://img.shields.io/badge/Python-3.10%20a%203.14-3776AB?style=for-the-badge&logo=python&logoColor=white)
28
+ ![Versão](https://img.shields.io/badge/vers%C3%A3o-3.15-2ea44f?style=for-the-badge)
29
29
  ![Status](https://img.shields.io/badge/status-alpha-orange?style=for-the-badge)
30
30
  ![Concorrência](https://img.shields.io/badge/concorr%C3%AAncia-loky-6f42c1?style=for-the-badge)
31
31
 
@@ -110,6 +110,8 @@ resultado = channel.get() # 100
110
110
 
111
111
  Se a função gerar uma exceção, ela permanece armazenada no `Future`. Quando existe um Channel, o objeto da exceção também é enviado para ele.
112
112
 
113
+ Os executores registrados pela `Task` são finalizados automaticamente quando o programa termina. Quando for necessário encerrar o pool antes do fim do programa, use `task.shutdown()`.
114
+
113
115
  ## `Channel`
114
116
 
115
117
  O `Channel` transporta valores entre produtores e consumidores por meio de uma `multiprocessing.Queue`.
@@ -1,7 +1,7 @@
1
1
  # PyChannel
2
2
 
3
- ![Python](https://img.shields.io/badge/Python-3.10%20%7C%203.11%20%7C%203.12-3776AB?style=for-the-badge&logo=python&logoColor=white)
4
- ![Versão](https://img.shields.io/badge/vers%C3%A3o-0.1.0-2ea44f?style=for-the-badge)
3
+ ![Python](https://img.shields.io/badge/Python-3.10%20a%203.14-3776AB?style=for-the-badge&logo=python&logoColor=white)
4
+ ![Versão](https://img.shields.io/badge/vers%C3%A3o-3.15-2ea44f?style=for-the-badge)
5
5
  ![Status](https://img.shields.io/badge/status-alpha-orange?style=for-the-badge)
6
6
  ![Concorrência](https://img.shields.io/badge/concorr%C3%AAncia-loky-6f42c1?style=for-the-badge)
7
7
 
@@ -84,7 +84,9 @@ resultado = channel.get() # 100
84
84
  | Com `Channel` e `Buffer` | O Channel recebe `False` durante o acúmulo e uma lista quando o lote fica pronto. |
85
85
  | Com `Buffer`, sem `Channel` | O Buffer é atualizado e o resultado individual continua disponível no `Future`. |
86
86
 
87
- Se a função gerar uma exceção, ela permanece armazenada no `Future`. Quando existe um Channel, o objeto da exceção também é enviado para ele.
87
+ Se a função gerar uma exceção, ela permanece armazenada no `Future`. Quando existe um Channel, o objeto da exceção também é enviado para ele.
88
+
89
+ Os executores registrados pela `Task` são finalizados automaticamente quando o programa termina. Quando for necessário encerrar o pool antes do fim do programa, use `task.shutdown()`.
88
90
 
89
91
  ## `Channel`
90
92
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "PyChannel"
7
- version = "0.1.3"
7
+ version = "1.5"
8
8
  description = "A Python concurrency library inspired by Go's goroutines and channels"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -47,4 +47,4 @@ include = ["PyChannel*"]
47
47
 
48
48
  [tool.pytest.ini_options]
49
49
  testpaths = ["tests"]
50
- addopts = "-ra"
50
+ addopts = "-ra"
File without changes
File without changes
File without changes