cmd-queue 0.1.20__py3-none-any.whl → 0.2.1__py3-none-any.whl

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.

Potentially problematic release.


This version of cmd-queue might be problematic. Click here for more details.

@@ -1,652 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: cmd_queue
3
- Version: 0.1.20
4
- Summary: The cmd_queue module for a DAG of bash commands
5
- Home-page: https://gitlab.kitware.com/computer-vision/cmd_queue
6
- Author: Kitware Inc., Jon Crall
7
- Author-email: kitware@kitware.com, jon.crall@kitware.com
8
- License: Apache 2
9
- Classifier: Development Status :: 4 - Beta
10
- Classifier: Intended Audience :: Developers
11
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
12
- Classifier: Topic :: Utilities
13
- Classifier: License :: OSI Approved :: Apache Software License
14
- Classifier: Programming Language :: Python :: 3.6
15
- Classifier: Programming Language :: Python :: 3.7
16
- Classifier: Programming Language :: Python :: 3.8
17
- Classifier: Programming Language :: Python :: 3.9
18
- Classifier: Programming Language :: Python :: 3.10
19
- Classifier: Programming Language :: Python :: 3.11
20
- Classifier: Programming Language :: Python :: 3.12
21
- Requires-Python: >=3.6
22
- Description-Content-Type: text/x-rst
23
- License-File: LICENSE
24
- Requires-Dist: ubelt >=1.3.0
25
- Requires-Dist: rich >=12.5.1
26
- Requires-Dist: scriptconfig >=0.7.9
27
- Requires-Dist: psutil >=5.9.1
28
- Requires-Dist: ruamel.yaml >=0.17.22
29
- Requires-Dist: numpy >=1.19.3 ; python_version < "3.10" and python_version >= "3.6.0"
30
- Requires-Dist: pandas >=1.4.0 ; python_version < "3.10" and python_version >= "3.9"
31
- Requires-Dist: numpy >=1.21.6 ; python_version < "3.11" and python_version >= "3.10"
32
- Requires-Dist: pandas >=1.4.0 ; python_version < "3.11" and python_version >= "3.10"
33
- Requires-Dist: networkx >=2.7 ; python_version < "3.11" and python_version >= "3.8"
34
- Requires-Dist: numpy >=1.23.2 ; python_version < "3.12" and python_version >= "3.11"
35
- Requires-Dist: pandas >=1.5.0 ; python_version < "3.12" and python_version >= "3.11"
36
- Requires-Dist: pandas >=1.1.5 ; python_version < "3.7" and python_version >= "3.6"
37
- Requires-Dist: pint >=0.10 ; python_version < "3.7" and python_version >= "3.6"
38
- Requires-Dist: networkx <=2.5.1,>=2.5.1 ; python_version < "3.7.0" and python_version >= "3.6.0"
39
- Requires-Dist: networkx >=2.6.2 ; python_version < "3.8" and python_version >= "3.7"
40
- Requires-Dist: pandas >=1.3.5 ; python_version < "3.8" and python_version >= "3.7"
41
- Requires-Dist: pandas >=1.4.0 ; python_version < "3.9" and python_version >= "3.8"
42
- Requires-Dist: networkx >=2.8 ; python_version < "4.0" and python_version >= "3.11"
43
- Requires-Dist: numpy >=1.26.0 ; python_version < "4.0" and python_version >= "3.12"
44
- Requires-Dist: pandas >=2.1.1 ; python_version < "4.0" and python_version >= "3.12"
45
- Requires-Dist: pint >=0.18 ; python_version >= "3.7"
46
- Provides-Extra: all
47
- Requires-Dist: ubelt >=1.3.0 ; extra == 'all'
48
- Requires-Dist: rich >=12.5.1 ; extra == 'all'
49
- Requires-Dist: scriptconfig >=0.7.9 ; extra == 'all'
50
- Requires-Dist: psutil >=5.9.1 ; extra == 'all'
51
- Requires-Dist: ruamel.yaml >=0.17.22 ; extra == 'all'
52
- Requires-Dist: xdoctest >=1.0.1 ; extra == 'all'
53
- Provides-Extra: all-strict
54
- Requires-Dist: ubelt ==1.3.0 ; extra == 'all-strict'
55
- Requires-Dist: rich ==12.5.1 ; extra == 'all-strict'
56
- Requires-Dist: scriptconfig ==0.7.9 ; extra == 'all-strict'
57
- Requires-Dist: psutil ==5.9.1 ; extra == 'all-strict'
58
- Requires-Dist: ruamel.yaml ==0.17.22 ; extra == 'all-strict'
59
- Requires-Dist: xdoctest ==1.0.1 ; extra == 'all-strict'
60
- Requires-Dist: numpy ==1.19.3 ; (python_version < "3.10" and python_version >= "3.6.0") and extra == 'all-strict'
61
- Requires-Dist: pandas ==1.4.0 ; (python_version < "3.10" and python_version >= "3.9") and extra == 'all-strict'
62
- Requires-Dist: coverage ==5.3.1 ; (python_version < "3.10" and python_version >= "3.9") and extra == 'all-strict'
63
- Requires-Dist: numpy ==1.21.6 ; (python_version < "3.11" and python_version >= "3.10") and extra == 'all-strict'
64
- Requires-Dist: pandas ==1.4.0 ; (python_version < "3.11" and python_version >= "3.10") and extra == 'all-strict'
65
- Requires-Dist: networkx ==2.7 ; (python_version < "3.11" and python_version >= "3.8") and extra == 'all-strict'
66
- Requires-Dist: numpy ==1.23.2 ; (python_version < "3.12" and python_version >= "3.11") and extra == 'all-strict'
67
- Requires-Dist: pandas ==1.5.0 ; (python_version < "3.12" and python_version >= "3.11") and extra == 'all-strict'
68
- Requires-Dist: pandas ==1.1.5 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'all-strict'
69
- Requires-Dist: pint ==0.10 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'all-strict'
70
- Requires-Dist: pytest ==6.2.0 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'all-strict'
71
- Requires-Dist: coverage ==6.1.1 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'all-strict'
72
- Requires-Dist: networkx <=2.5.1,==2.5.1 ; (python_version < "3.7.0" and python_version >= "3.6.0") and extra == 'all-strict'
73
- Requires-Dist: networkx ==2.6.2 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'all-strict'
74
- Requires-Dist: pandas ==1.3.5 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'all-strict'
75
- Requires-Dist: coverage ==6.1.1 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'all-strict'
76
- Requires-Dist: pandas ==1.4.0 ; (python_version < "3.9" and python_version >= "3.8") and extra == 'all-strict'
77
- Requires-Dist: coverage ==6.1.1 ; (python_version < "3.9" and python_version >= "3.8") and extra == 'all-strict'
78
- Requires-Dist: networkx ==2.8 ; (python_version < "4.0" and python_version >= "3.11") and extra == 'all-strict'
79
- Requires-Dist: numpy ==1.26.0 ; (python_version < "4.0" and python_version >= "3.12") and extra == 'all-strict'
80
- Requires-Dist: pandas ==2.1.1 ; (python_version < "4.0" and python_version >= "3.12") and extra == 'all-strict'
81
- Requires-Dist: coverage ==6.1.1 ; (python_version >= "3.10") and extra == 'all-strict'
82
- Requires-Dist: pytest-cov ==3.0.0 ; (python_version >= "3.6.0") and extra == 'all-strict'
83
- Requires-Dist: pint ==0.18 ; (python_version >= "3.7") and extra == 'all-strict'
84
- Requires-Dist: pytest ==7.1.0 ; (python_version >= "3.7") and extra == 'all-strict'
85
- Requires-Dist: textual ==0.1.18 ; (python_version >= "3.7") and extra == 'all-strict'
86
- Requires-Dist: numpy >=1.19.3 ; (python_version < "3.10" and python_version >= "3.6.0") and extra == 'all'
87
- Requires-Dist: pandas >=1.4.0 ; (python_version < "3.10" and python_version >= "3.9") and extra == 'all'
88
- Requires-Dist: coverage >=5.3.1 ; (python_version < "3.10" and python_version >= "3.9") and extra == 'all'
89
- Requires-Dist: numpy >=1.21.6 ; (python_version < "3.11" and python_version >= "3.10") and extra == 'all'
90
- Requires-Dist: pandas >=1.4.0 ; (python_version < "3.11" and python_version >= "3.10") and extra == 'all'
91
- Requires-Dist: networkx >=2.7 ; (python_version < "3.11" and python_version >= "3.8") and extra == 'all'
92
- Requires-Dist: numpy >=1.23.2 ; (python_version < "3.12" and python_version >= "3.11") and extra == 'all'
93
- Requires-Dist: pandas >=1.5.0 ; (python_version < "3.12" and python_version >= "3.11") and extra == 'all'
94
- Requires-Dist: pandas >=1.1.5 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'all'
95
- Requires-Dist: pint >=0.10 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'all'
96
- Requires-Dist: pytest >=6.2.0 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'all'
97
- Requires-Dist: coverage >=6.1.1 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'all'
98
- Requires-Dist: networkx <=2.5.1,>=2.5.1 ; (python_version < "3.7.0" and python_version >= "3.6.0") and extra == 'all'
99
- Requires-Dist: networkx >=2.6.2 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'all'
100
- Requires-Dist: pandas >=1.3.5 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'all'
101
- Requires-Dist: coverage >=6.1.1 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'all'
102
- Requires-Dist: pandas >=1.4.0 ; (python_version < "3.9" and python_version >= "3.8") and extra == 'all'
103
- Requires-Dist: coverage >=6.1.1 ; (python_version < "3.9" and python_version >= "3.8") and extra == 'all'
104
- Requires-Dist: networkx >=2.8 ; (python_version < "4.0" and python_version >= "3.11") and extra == 'all'
105
- Requires-Dist: numpy >=1.26.0 ; (python_version < "4.0" and python_version >= "3.12") and extra == 'all'
106
- Requires-Dist: pandas >=2.1.1 ; (python_version < "4.0" and python_version >= "3.12") and extra == 'all'
107
- Requires-Dist: coverage >=6.1.1 ; (python_version >= "3.10") and extra == 'all'
108
- Requires-Dist: pytest-cov >=3.0.0 ; (python_version >= "3.6.0") and extra == 'all'
109
- Requires-Dist: pint >=0.18 ; (python_version >= "3.7") and extra == 'all'
110
- Requires-Dist: pytest >=7.1.0 ; (python_version >= "3.7") and extra == 'all'
111
- Requires-Dist: textual >=0.1.18 ; (python_version >= "3.7") and extra == 'all'
112
- Provides-Extra: docs
113
- Requires-Dist: sphinx >=5.0.1 ; extra == 'docs'
114
- Requires-Dist: sphinx-autobuild >=2021.3.14 ; extra == 'docs'
115
- Requires-Dist: sphinx-rtd-theme >=1.0.0 ; extra == 'docs'
116
- Requires-Dist: sphinxcontrib-napoleon >=0.7 ; extra == 'docs'
117
- Requires-Dist: sphinx-autoapi >=1.8.4 ; extra == 'docs'
118
- Requires-Dist: Pygments >=2.9.0 ; extra == 'docs'
119
- Requires-Dist: myst-parser >=0.18.0 ; extra == 'docs'
120
- Requires-Dist: sphinx-reredirects >=0.0.1 ; extra == 'docs'
121
- Provides-Extra: docs-strict
122
- Requires-Dist: sphinx ==5.0.1 ; extra == 'docs-strict'
123
- Requires-Dist: sphinx-autobuild ==2021.3.14 ; extra == 'docs-strict'
124
- Requires-Dist: sphinx-rtd-theme ==1.0.0 ; extra == 'docs-strict'
125
- Requires-Dist: sphinxcontrib-napoleon ==0.7 ; extra == 'docs-strict'
126
- Requires-Dist: sphinx-autoapi ==1.8.4 ; extra == 'docs-strict'
127
- Requires-Dist: Pygments ==2.9.0 ; extra == 'docs-strict'
128
- Requires-Dist: myst-parser ==0.18.0 ; extra == 'docs-strict'
129
- Requires-Dist: sphinx-reredirects ==0.0.1 ; extra == 'docs-strict'
130
- Provides-Extra: optional
131
- Provides-Extra: optional-strict
132
- Requires-Dist: textual ==0.1.18 ; (python_version >= "3.7") and extra == 'optional-strict'
133
- Requires-Dist: textual >=0.1.18 ; (python_version >= "3.7") and extra == 'optional'
134
- Provides-Extra: runtime
135
- Requires-Dist: ubelt >=1.3.0 ; extra == 'runtime'
136
- Requires-Dist: rich >=12.5.1 ; extra == 'runtime'
137
- Requires-Dist: scriptconfig >=0.7.9 ; extra == 'runtime'
138
- Requires-Dist: psutil >=5.9.1 ; extra == 'runtime'
139
- Requires-Dist: ruamel.yaml >=0.17.22 ; extra == 'runtime'
140
- Provides-Extra: runtime-strict
141
- Requires-Dist: ubelt ==1.3.0 ; extra == 'runtime-strict'
142
- Requires-Dist: rich ==12.5.1 ; extra == 'runtime-strict'
143
- Requires-Dist: scriptconfig ==0.7.9 ; extra == 'runtime-strict'
144
- Requires-Dist: psutil ==5.9.1 ; extra == 'runtime-strict'
145
- Requires-Dist: ruamel.yaml ==0.17.22 ; extra == 'runtime-strict'
146
- Requires-Dist: numpy ==1.19.3 ; (python_version < "3.10" and python_version >= "3.6.0") and extra == 'runtime-strict'
147
- Requires-Dist: pandas ==1.4.0 ; (python_version < "3.10" and python_version >= "3.9") and extra == 'runtime-strict'
148
- Requires-Dist: numpy ==1.21.6 ; (python_version < "3.11" and python_version >= "3.10") and extra == 'runtime-strict'
149
- Requires-Dist: pandas ==1.4.0 ; (python_version < "3.11" and python_version >= "3.10") and extra == 'runtime-strict'
150
- Requires-Dist: networkx ==2.7 ; (python_version < "3.11" and python_version >= "3.8") and extra == 'runtime-strict'
151
- Requires-Dist: numpy ==1.23.2 ; (python_version < "3.12" and python_version >= "3.11") and extra == 'runtime-strict'
152
- Requires-Dist: pandas ==1.5.0 ; (python_version < "3.12" and python_version >= "3.11") and extra == 'runtime-strict'
153
- Requires-Dist: pandas ==1.1.5 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'runtime-strict'
154
- Requires-Dist: pint ==0.10 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'runtime-strict'
155
- Requires-Dist: networkx <=2.5.1,==2.5.1 ; (python_version < "3.7.0" and python_version >= "3.6.0") and extra == 'runtime-strict'
156
- Requires-Dist: networkx ==2.6.2 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'runtime-strict'
157
- Requires-Dist: pandas ==1.3.5 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'runtime-strict'
158
- Requires-Dist: pandas ==1.4.0 ; (python_version < "3.9" and python_version >= "3.8") and extra == 'runtime-strict'
159
- Requires-Dist: networkx ==2.8 ; (python_version < "4.0" and python_version >= "3.11") and extra == 'runtime-strict'
160
- Requires-Dist: numpy ==1.26.0 ; (python_version < "4.0" and python_version >= "3.12") and extra == 'runtime-strict'
161
- Requires-Dist: pandas ==2.1.1 ; (python_version < "4.0" and python_version >= "3.12") and extra == 'runtime-strict'
162
- Requires-Dist: pint ==0.18 ; (python_version >= "3.7") and extra == 'runtime-strict'
163
- Requires-Dist: numpy >=1.19.3 ; (python_version < "3.10" and python_version >= "3.6.0") and extra == 'runtime'
164
- Requires-Dist: pandas >=1.4.0 ; (python_version < "3.10" and python_version >= "3.9") and extra == 'runtime'
165
- Requires-Dist: numpy >=1.21.6 ; (python_version < "3.11" and python_version >= "3.10") and extra == 'runtime'
166
- Requires-Dist: pandas >=1.4.0 ; (python_version < "3.11" and python_version >= "3.10") and extra == 'runtime'
167
- Requires-Dist: networkx >=2.7 ; (python_version < "3.11" and python_version >= "3.8") and extra == 'runtime'
168
- Requires-Dist: numpy >=1.23.2 ; (python_version < "3.12" and python_version >= "3.11") and extra == 'runtime'
169
- Requires-Dist: pandas >=1.5.0 ; (python_version < "3.12" and python_version >= "3.11") and extra == 'runtime'
170
- Requires-Dist: pandas >=1.1.5 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'runtime'
171
- Requires-Dist: pint >=0.10 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'runtime'
172
- Requires-Dist: networkx <=2.5.1,>=2.5.1 ; (python_version < "3.7.0" and python_version >= "3.6.0") and extra == 'runtime'
173
- Requires-Dist: networkx >=2.6.2 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'runtime'
174
- Requires-Dist: pandas >=1.3.5 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'runtime'
175
- Requires-Dist: pandas >=1.4.0 ; (python_version < "3.9" and python_version >= "3.8") and extra == 'runtime'
176
- Requires-Dist: networkx >=2.8 ; (python_version < "4.0" and python_version >= "3.11") and extra == 'runtime'
177
- Requires-Dist: numpy >=1.26.0 ; (python_version < "4.0" and python_version >= "3.12") and extra == 'runtime'
178
- Requires-Dist: pandas >=2.1.1 ; (python_version < "4.0" and python_version >= "3.12") and extra == 'runtime'
179
- Requires-Dist: pint >=0.18 ; (python_version >= "3.7") and extra == 'runtime'
180
- Provides-Extra: tests
181
- Requires-Dist: xdoctest >=1.0.1 ; extra == 'tests'
182
- Provides-Extra: tests-strict
183
- Requires-Dist: xdoctest ==1.0.1 ; extra == 'tests-strict'
184
- Requires-Dist: coverage ==5.3.1 ; (python_version < "3.10" and python_version >= "3.9") and extra == 'tests-strict'
185
- Requires-Dist: pytest ==6.2.0 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'tests-strict'
186
- Requires-Dist: coverage ==6.1.1 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'tests-strict'
187
- Requires-Dist: coverage ==6.1.1 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'tests-strict'
188
- Requires-Dist: coverage ==6.1.1 ; (python_version < "3.9" and python_version >= "3.8") and extra == 'tests-strict'
189
- Requires-Dist: coverage ==6.1.1 ; (python_version >= "3.10") and extra == 'tests-strict'
190
- Requires-Dist: pytest-cov ==3.0.0 ; (python_version >= "3.6.0") and extra == 'tests-strict'
191
- Requires-Dist: pytest ==7.1.0 ; (python_version >= "3.7") and extra == 'tests-strict'
192
- Requires-Dist: coverage >=5.3.1 ; (python_version < "3.10" and python_version >= "3.9") and extra == 'tests'
193
- Requires-Dist: pytest >=6.2.0 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'tests'
194
- Requires-Dist: coverage >=6.1.1 ; (python_version < "3.7" and python_version >= "3.6") and extra == 'tests'
195
- Requires-Dist: coverage >=6.1.1 ; (python_version < "3.8" and python_version >= "3.7") and extra == 'tests'
196
- Requires-Dist: coverage >=6.1.1 ; (python_version < "3.9" and python_version >= "3.8") and extra == 'tests'
197
- Requires-Dist: coverage >=6.1.1 ; (python_version >= "3.10") and extra == 'tests'
198
- Requires-Dist: pytest-cov >=3.0.0 ; (python_version >= "3.6.0") and extra == 'tests'
199
- Requires-Dist: pytest >=7.1.0 ; (python_version >= "3.7") and extra == 'tests'
200
-
201
- Command Queue - cmd_queue
202
- =========================
203
-
204
- .. .. |Appveyor| |Codecov|
205
-
206
- |Pypi| |Downloads| |GitlabCIPipeline| |GitlabCICoverage| |ReadTheDocs|
207
-
208
-
209
- +------------------+-------------------------------------------------------------------------------------+
210
- | Read the docs | https://cmd-queue.readthedocs.io |
211
- +------------------+-------------------------------------------------------------------------------------+
212
- | Gitlab | https://gitlab.kitware.com/computer-vision/cmd_queue |
213
- +------------------+-------------------------------------------------------------------------------------+
214
- | Pypi | https://pypi.org/project/cmd_queue |
215
- +------------------+-------------------------------------------------------------------------------------+
216
- | Slides | https://docs.google.com/presentation/d/1BjJkjMx6bxu1uek-hAGpwj760u9rraVn7st8J5OsZME |
217
- +------------------+-------------------------------------------------------------------------------------+
218
-
219
-
220
- This is a simple module for "generating" a bash script that schedules multiples
221
- jobs (in parallel if possible) on a single machine. There are 3 backends with
222
- increasing levels of complexity: serial, tmux, and slurm.
223
-
224
- In serial mode, a single bash script gets written that executes your jobs in
225
- sequence. There are no external dependencies
226
-
227
- In tmux mode, multiple tmux sessions get opened and each of them executes your
228
- independent parts of your jobs. Dependencies are handled.
229
-
230
- In slurm mode, a real heavy-weight scheduling algorithm is used. In this mode
231
- we simply convert your jobs to slurm commands and execute them.
232
-
233
- Under the hood we build a DAG based on your specified dependencies and use this
234
- to appropriately order jobs.
235
-
236
- By default, bash scripts that would execute your jobs print to the console.
237
- This gives the user fine-grained control if they only want to run a subset of a
238
- pipeline manually. But if asked to run, cmd_queue will execute the bash jobs.
239
-
240
- Features
241
- ~~~~~~~~
242
-
243
- * Bash command scheduling
244
-
245
- * Execution is optional, can just print commands instead
246
-
247
- * No-parallelism always-available serial backend
248
-
249
- * Tmux based lightweight backend
250
-
251
- * Slurm based heavyweight backend
252
-
253
- * Python and Bash interface
254
-
255
- * Rich monitoring / live-control
256
-
257
-
258
- Installation
259
- ============
260
-
261
- The cmd_queue package is available on pypi.
262
-
263
- .. code:: bash
264
-
265
- pip install cmd_queue
266
-
267
- The serial queue backend will always work. To gain access other backends you
268
- must install their associated dependencies. The tmux backend is the easiest and
269
- simply requires that tmux is installed (e.g. ``sudo apt install tmux`` on
270
- Debian systems).
271
-
272
- Other backends require more complex setups. The slurm backend will require that
273
- `slurm is installed <https://slurm.schedmd.com/quickstart_admin.html>`_ and the
274
- daemon is running. The slurm backend is functional and tested, but improvements
275
- can still be made (help wanted). The airflow backend similarly requires a
276
- configured airflow server, but is not fully functional or tested (contributions
277
- to make airflow work / easier are wanted!).
278
-
279
-
280
- Tmux Queue Demo
281
- ===============
282
-
283
- After installing, the following command runs a demo of the tmux queue:
284
-
285
- .. code:: bash
286
-
287
- # Reproduce the
288
- INTERACTIVE_TEST=1 xdoctest -m cmd_queue.tmux_queue TMUXMultiQueue.monitor:1
289
-
290
-
291
- This executes the following code, which creates two parallel tmux workers and
292
- submits several bash jobs with non-trivial dependencies.
293
-
294
- .. code:: python
295
-
296
- # xdoctest: +REQUIRES(env:INTERACTIVE_TEST)
297
- from cmd_queue.tmux_queue import * # NOQA
298
- # Setup a lot of longer running jobs
299
- n = 2
300
- self = TMUXMultiQueue(size=n, name='demo_cmd_queue')
301
- first_job = None
302
- for i in range(n):
303
- prev_job = None
304
- for j in range(4):
305
- command = f'sleep 1 && echo "This is job {i}.{j}"'
306
- job = self.submit(command, depends=prev_job)
307
- prev_job = job
308
- first_job = first_job or job
309
- command = f'sleep 1 && echo "this is the last job"'
310
- job = self.submit(command, depends=[prev_job, first_job])
311
- self.print_commands(style='rich')
312
- self.print_graph()
313
- if self.is_available():
314
- self.run(block=True, other_session_handler='kill')
315
-
316
-
317
- When running the ``print_commands`` command will first display all of the submitted
318
- commands that will be distributed across multiple new tmux sessions. These are
319
- the commands will be executed. This is useful for spot checking that your bash
320
- command templating is correct before the queue is executed with ``run``.
321
-
322
-
323
- .. .. Screenshot of the print_commands output
324
- .. image:: https://i.imgur.com/rVbyHzM.png
325
- :height: 300px
326
- :align: left
327
-
328
-
329
- The ``print_graph`` command will render the DAG to be executed using
330
- `network text <https://networkx.org/documentation/stable/reference/readwrite/generated/networkx.readwrite.text.write_network_text.html#networkx.readwrite.text.write_network_text>`_.
331
- And finally ``run`` is called with ``block=True``, which starts executing the
332
- DAG and displays progress and job status in rich or textual monitor.
333
-
334
- .. .. image:: https://i.imgur.com/RbyTvP9.png
335
- .. :height: 300px
336
- .. :align: left
337
-
338
- .. .. Animated gif of the queue from dev/record_demo.sh
339
- .. image:: https://i.imgur.com/4mxFIMk.gif
340
- :height: 300px
341
- :align: left
342
-
343
-
344
- While this is running it is possible to simply attach to a tmux sessions (e.g.
345
- ``tmux a``) and inspect a specific queue while it is running. (We recommend
346
- using ``<ctrl-b>s`` inside of a tmux session to view and navigate through the
347
- tmux sessions). Unlike the slurm backend, the entire execution of the DAG is
348
- entirely transparent to the developer! The following screenshot shows the tmux
349
- sessions spawned while running this demo.
350
-
351
- .. .. Screenshot of the tmux sessions
352
- .. image:: https://i.imgur.com/46LRK8M.png
353
- :height: 300px
354
- :align: left
355
-
356
- By default, if there are no errors, these sessions will exit after execution
357
- completes, but this is configurable. Likewise if there are errors, the tmux
358
- sessions will persist to allow for debugging.
359
-
360
-
361
- Modivation
362
- ==========
363
- Recently, I needed to run several jobs on 4 jobs across 2 GPUs and then execute
364
- a script after all of them were done. What I should have done was use slurm or
365
- some other proper queuing system to schedule the jobs, but instead I wrote my
366
- own hacky scheduler using tmux. I opened N (number of parallel workers) tmux
367
- sessions and then I ran independent jobs in each different sessions.
368
-
369
- This worked unreasonably well for my use cases, and it was nice to be able to effectively schedule jobs without heavyweight software like slurm on my machine.
370
-
371
- Eventually I did get slurm on my machine, and I abstracted the API of my
372
- tmux_queue to be a general "command queue" that can use 1 of 3 backends:
373
- serial, tmux, or slurm.
374
-
375
-
376
- Niche
377
- =====
378
- There are many DAG schedulers out there:
379
-
380
- * airflow
381
- * luigi
382
- * submitit
383
- * rq_scheduler
384
-
385
-
386
- The the niche for this is when you have large pipelines of bash commands that
387
- depend on each other and you want to template out those parameters with logic
388
- that you define in Python.
389
-
390
- We plan on adding an airflow backend.
391
-
392
-
393
- Examples
394
- ========
395
-
396
-
397
- All of the dependency checking and book keeping logic is handled in bash
398
- itself. Write (or better yet template) your bash scripts in Python, and then
399
- use cmd_queue to "transpile" these sequences of commands to pure bash.
400
-
401
-
402
- .. code:: python
403
-
404
- import cmd_queue
405
- self = cmd_queue.Queue.create(name='demo_queue', backend='serial')
406
- job1 = self.submit('echo hello && sleep 0.5')
407
- job2 = self.submit('echo world && sleep 0.5', depends=[job1])
408
- job3 = self.submit('echo foo && sleep 0.5')
409
- job4 = self.submit('echo bar && sleep 0.5')
410
- job5 = self.submit('echo spam && sleep 0.5', depends=[job1])
411
- job6 = self.submit('echo spam && sleep 0.5')
412
- job7 = self.submit('echo err && false')
413
- job8 = self.submit('echo spam && sleep 0.5')
414
- job9 = self.submit('echo eggs && sleep 0.5', depends=[job8])
415
- job10 = self.submit('echo bazbiz && sleep 0.5', depends=[job9])
416
-
417
- # Display the "user-friendly" pure bash
418
- self.print_commands()
419
-
420
- # Display the real bash that gets executed under the hood
421
- # that is independencly executable, tracks the success / failure of each job,
422
- # and manages dependencies.
423
- self.print_commands(1, 1)
424
-
425
- # Blocking will display a job monitor while it waits for everything to
426
- # complete
427
- self.run(block=True)
428
-
429
-
430
- This prints the bash commands in an appropriate order to resolve dependencies.
431
-
432
-
433
- .. code:: bash
434
-
435
- # --- /home/joncrall/.cache/base_queue/demo_queue_2022-04-08_cc9d551e/demo_queue_2022-04-08_cc9d551e.sh
436
-
437
- #!/bin/bash
438
- #
439
- # Jobs
440
- #
441
- ### Command 1 / 10 - demo_queue-job-0
442
- echo hello && sleep 0.5
443
- #
444
- ### Command 2 / 10 - demo_queue-job-1
445
- echo world && sleep 0.5
446
- #
447
- ### Command 3 / 10 - demo_queue-job-2
448
- echo foo && sleep 0.5
449
- #
450
- ### Command 4 / 10 - demo_queue-job-3
451
- echo bar && sleep 0.5
452
- #
453
- ### Command 5 / 10 - demo_queue-job-4
454
- echo spam && sleep 0.5
455
- #
456
- ### Command 6 / 10 - demo_queue-job-5
457
- echo spam && sleep 0.5
458
- #
459
- ### Command 7 / 10 - demo_queue-job-6
460
- echo err && false
461
- #
462
- ### Command 8 / 10 - demo_queue-job-7
463
- echo spam && sleep 0.5
464
- #
465
- ### Command 9 / 10 - demo_queue-job-8
466
- echo eggs && sleep 0.5
467
- #
468
- ### Command 10 / 10 - demo_queue-job-9
469
- echo bazbiz && sleep 0.5
470
-
471
-
472
-
473
- .. code:: python
474
-
475
- # Need to tell the tmux queue how many processes can run at the same time
476
- import cmd_queue
477
- self = cmd_queue.Queue.create(size=4, name='demo_queue', backend='tmux')
478
- job1 = self.submit('echo hello && sleep 0.5')
479
- job2 = self.submit('echo world && sleep 0.5', depends=[job1])
480
- job3 = self.submit('echo foo && sleep 0.5')
481
- job4 = self.submit('echo bar && sleep 0.5')
482
- job5 = self.submit('echo spam && sleep 0.5', depends=[job1])
483
- job6 = self.submit('echo spam && sleep 0.5')
484
- job7 = self.submit('echo err && false')
485
- job8 = self.submit('echo spam && sleep 0.5')
486
- job9 = self.submit('echo eggs && sleep 0.5', depends=[job8])
487
- job10 = self.submit('echo bazbiz && sleep 0.5', depends=[job9])
488
-
489
- # Display the "user-friendly" pure bash
490
- self.print_commands()
491
-
492
- # Display the real bash that gets executed under the hood
493
- # that is independencly executable, tracks the success / failure of each job,
494
- # and manages dependencies.
495
- self.print_commands(1, 1)
496
-
497
- # Blocking will display a job monitor while it waits for everything to
498
- # complete
499
- self.run(block=True)
500
-
501
-
502
- This prints the sequence of bash commands that will be executed in each tmux session.
503
-
504
- .. code:: bash
505
-
506
- # --- /home/joncrall/.cache/base_queue/demo_queue_2022-04-08_a1ef7600/queue_demo_queue_0_2022-04-08_a1ef7600.sh
507
-
508
- #!/bin/bash
509
- #
510
- # Jobs
511
- #
512
- ### Command 1 / 3 - demo_queue-job-7
513
- echo spam && sleep 0.5
514
- #
515
- ### Command 2 / 3 - demo_queue-job-8
516
- echo eggs && sleep 0.5
517
- #
518
- ### Command 3 / 3 - demo_queue-job-9
519
- echo bazbiz && sleep 0.5
520
-
521
- # --- /home/joncrall/.cache/base_queue/demo_queue_2022-04-08_a1ef7600/queue_demo_queue_1_2022-04-08_a1ef7600.sh
522
-
523
- #!/bin/bash
524
- #
525
- # Jobs
526
- #
527
- ### Command 1 / 2 - demo_queue-job-2
528
- echo foo && sleep 0.5
529
- #
530
- ### Command 2 / 2 - demo_queue-job-6
531
- echo err && false
532
-
533
- # --- /home/joncrall/.cache/base_queue/demo_queue_2022-04-08_a1ef7600/queue_demo_queue_2_2022-04-08_a1ef7600.sh
534
-
535
- #!/bin/bash
536
- #
537
- # Jobs
538
- #
539
- ### Command 1 / 2 - demo_queue-job-0
540
- echo hello && sleep 0.5
541
- #
542
- ### Command 2 / 2 - demo_queue-job-5
543
- echo spam && sleep 0.5
544
-
545
- # --- /home/joncrall/.cache/base_queue/demo_queue_2022-04-08_a1ef7600/queue_demo_queue_3_2022-04-08_a1ef7600.sh
546
-
547
- #!/bin/bash
548
- #
549
- # Jobs
550
- #
551
- ### Command 1 / 1 - demo_queue-job-3
552
- echo bar && sleep 0.5
553
-
554
- # --- /home/joncrall/.cache/base_queue/demo_queue_2022-04-08_a1ef7600/queue_demo_queue_4_2022-04-08_a1ef7600.sh
555
-
556
- #!/bin/bash
557
- #
558
- # Jobs
559
- #
560
- ### Command 1 / 1 - demo_queue-job-4
561
- echo spam && sleep 0.5
562
-
563
- # --- /home/joncrall/.cache/base_queue/demo_queue_2022-04-08_a1ef7600/queue_demo_queue_5_2022-04-08_a1ef7600.sh
564
-
565
- #!/bin/bash
566
- #
567
- # Jobs
568
- #
569
- ### Command 1 / 1 - demo_queue-job-1
570
- echo world && sleep 0.5
571
-
572
-
573
-
574
- Slurm mode is the real deal. But you need slurm installed on your machint to
575
- use it. Asking for tmux is a might ligher weight tool. We can specify slurm
576
- options here
577
-
578
- .. code:: python
579
-
580
- import cmd_queue
581
- self = cmd_queue.Queue.create(name='demo_queue', backend='slurm')
582
- job1 = self.submit('echo hello && sleep 0.5', cpus=4, mem='8GB')
583
- job2 = self.submit('echo world && sleep 0.5', depends=[job1], parition='default')
584
- job3 = self.submit('echo foo && sleep 0.5')
585
- job4 = self.submit('echo bar && sleep 0.5')
586
- job5 = self.submit('echo spam && sleep 0.5', depends=[job1])
587
- job6 = self.submit('echo spam && sleep 0.5')
588
- job7 = self.submit('echo err && false')
589
- job8 = self.submit('echo spam && sleep 0.5')
590
- job9 = self.submit('echo eggs && sleep 0.5', depends=[job8])
591
- job10 = self.submit('echo bazbiz && sleep 0.5', depends=[job9])
592
-
593
- # Display the "user-friendly" pure bash
594
- self.print_commands()
595
-
596
- # Display the real bash that gets executed under the hood
597
- # that is independencly executable, tracks the success / failure of each job,
598
- # and manages dependencies.
599
- self.print_commands(1, 1)
600
-
601
- # Blocking will display a job monitor while it waits for everything to
602
- # complete
603
- self.run(block=True)
604
-
605
-
606
- This prints the very simple slurm submission script:
607
-
608
- .. code:: bash
609
-
610
- # --- /home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/demo_queue-20220408T170615-a9e238b5.sh
611
-
612
- mkdir -p "$HOME/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs"
613
- JOB_000=$(sbatch --job-name="J0000-demo_queue-20220408T170615-a9e238b5" --cpus-per-task=4 --mem=8000 --output="/home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs/J0000-demo_queue-20220408T170615-a9e238b5.sh" --wrap 'echo hello && sleep 0.5' --parsable)
614
- JOB_001=$(sbatch --job-name="J0002-demo_queue-20220408T170615-a9e238b5" --output="/home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs/J0002-demo_queue-20220408T170615-a9e238b5.sh" --wrap 'echo foo && sleep 0.5' --parsable)
615
- JOB_002=$(sbatch --job-name="J0003-demo_queue-20220408T170615-a9e238b5" --output="/home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs/J0003-demo_queue-20220408T170615-a9e238b5.sh" --wrap 'echo bar && sleep 0.5' --parsable)
616
- JOB_003=$(sbatch --job-name="J0005-demo_queue-20220408T170615-a9e238b5" --output="/home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs/J0005-demo_queue-20220408T170615-a9e238b5.sh" --wrap 'echo spam && sleep 0.5' --parsable)
617
- JOB_004=$(sbatch --job-name="J0006-demo_queue-20220408T170615-a9e238b5" --output="/home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs/J0006-demo_queue-20220408T170615-a9e238b5.sh" --wrap 'echo err && false' --parsable)
618
- JOB_005=$(sbatch --job-name="J0007-demo_queue-20220408T170615-a9e238b5" --output="/home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs/J0007-demo_queue-20220408T170615-a9e238b5.sh" --wrap 'echo spam && sleep 0.5' --parsable)
619
- JOB_006=$(sbatch --job-name="J0001-demo_queue-20220408T170615-a9e238b5" --output="/home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs/J0001-demo_queue-20220408T170615-a9e238b5.sh" --wrap 'echo world && sleep 0.5' "--dependency=afterok:${JOB_000}" --parsable)
620
- JOB_007=$(sbatch --job-name="J0004-demo_queue-20220408T170615-a9e238b5" --output="/home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs/J0004-demo_queue-20220408T170615-a9e238b5.sh" --wrap 'echo spam && sleep 0.5' "--dependency=afterok:${JOB_000}" --parsable)
621
- JOB_008=$(sbatch --job-name="J0008-demo_queue-20220408T170615-a9e238b5" --output="/home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs/J0008-demo_queue-20220408T170615-a9e238b5.sh" --wrap 'echo eggs && sleep 0.5' "--dependency=afterok:${JOB_005}" --parsable)
622
- JOB_009=$(sbatch --job-name="J0009-demo_queue-20220408T170615-a9e238b5" --output="/home/joncrall/.cache/slurm_queue/demo_queue-20220408T170615-a9e238b5/logs/J0009-demo_queue-20220408T170615-a9e238b5.sh" --wrap 'echo bazbiz && sleep 0.5' "--dependency=afterok:${JOB_008}" --parsable)
623
-
624
-
625
-
626
- .. |Pypi| image:: https://img.shields.io/pypi/v/cmd_queue.svg
627
- :target: https://pypi.python.org/pypi/cmd_queue
628
-
629
- .. |Downloads| image:: https://img.shields.io/pypi/dm/cmd_queue.svg
630
- :target: https://pypistats.org/packages/cmd_queue
631
-
632
- .. |ReadTheDocs| image:: https://readthedocs.org/projects/cmd-queue/badge/?version=release
633
- :target: https://cmd-queue.readthedocs.io/en/release/
634
-
635
- .. # See: https://ci.appveyor.com/project/jon.crall/cmd_queue/settings/badges
636
- .. |Appveyor| image:: https://ci.appveyor.com/api/projects/status/py3s2d6tyfjc8lm3/branch/main?svg=true
637
- :target: https://ci.appveyor.com/project/jon.crall/cmd_queue/branch/main
638
-
639
- .. |GitlabCIPipeline| image:: https://gitlab.kitware.com/computer-vision/cmd_queue/badges/main/pipeline.svg
640
- :target: https://gitlab.kitware.com/computer-vision/cmd_queue/-/jobs
641
-
642
- .. |GitlabCICoverage| image:: https://gitlab.kitware.com/computer-vision/cmd_queue/badges/main/coverage.svg?job=coverage
643
- :target: https://gitlab.kitware.com/computer-vision/cmd_queue/commits/main
644
-
645
- .. |CircleCI| image:: https://circleci.com/gh/Erotemic/cmd_queue.svg?style=svg
646
- :target: https://circleci.com/gh/Erotemic/cmd_queue
647
-
648
- .. |Travis| image:: https://img.shields.io/travis/Erotemic/cmd_queue/main.svg?label=Travis%20CI
649
- :target: https://travis-ci.org/Erotemic/cmd_queue
650
-
651
- .. |Codecov| image:: https://codecov.io/github/Erotemic/cmd_queue/badge.svg?branch=main&service=github
652
- :target: https://codecov.io/github/Erotemic/cmd_queue?branch=main