Skip to content

Commit 589388d

Browse files
committed
Merge remote-tracking branch 'origin/development' into development
2 parents 7359bd6 + d994cb7 commit 589388d

File tree

8 files changed

+97
-30
lines changed

8 files changed

+97
-30
lines changed

Diff for: source-code/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ to create it. There is some material not covered in the presentation as well.
2828
configuration files.
2929
1. `data-formats`: illustrates how to deal with data formats such as CSV
3030
files, binary data and XML.
31+
1. `directory-entrypoint`: illustrates how to define an application entry point in
32+
a directory.
3133
1. `enviroment-variables`: illustrates how to use environment variables to set paths
3234
in a script.
3335
1. `hydra`: Facebook Hydra application framework illustration.

Diff for: source-code/directory-entrypoint/README.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Directory entry point
2+
3+
Using `__main__.py` as an entry point, the Python interpreter can run a
4+
directory.
5+
6+
## What is it?
7+
8+
1. `messenger`: directory containing the application.
9+
1. `messenger/__main__.py`: Python application entry point.
10+
1. `messenger/messenger.py`: Python module defining some functions for the
11+
application.
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import argparse
2+
import messenger
3+
import sys
4+
5+
6+
arg_parser = argparse.ArgumentParser(description='say something to the user')
7+
arg_parser.add_argument('--hello', action='store_true', help='say hello')
8+
arg_parser.add_argument('--bye', action='store_true', help='say bye')
9+
arg_parser.add_argument('name', help='name to talk to')
10+
options = arg_parser.parse_args()
11+
12+
if options.hello:
13+
messenger.say_hello(options.name)
14+
if options.bye:
15+
messenger.say_bye(options.name)
16+
if not (options.hello or options.bye):
17+
print(f"don't know what to say to {options.name}", file=sys.stderr)
18+
sys.exit(1)
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def say_hello(name):
2+
print(f'hello {name}')
3+
4+
def say_bye(name):
5+
print(f'bye {name}')

Diff for: source-code/processes/monitor.py

+13-28
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def find_ancestor(pid=None, username=None):
5050
for parent in reversed(parents):
5151
if parent.username() == username:
5252
return parent
53+
return process
5354

5455

5556
def get_cmdline(process):
@@ -128,21 +129,6 @@ def process_status(process, metrics):
128129
return ','.join(status)
129130

130131

131-
def get_filename_suffix(file_id):
132-
filename = ''
133-
if 'PBS_JOBID' in os.environ:
134-
filename += f'_{os.environ["PBS_JOBID"]}'
135-
if 'PBS_ARRAYID' in os.environ:
136-
filename += f'_{os.environ["PBS_ARRAYJOBID"]}'
137-
if file_id:
138-
filename += f'_{file_id}'
139-
return f'{filename}.txt'
140-
141-
142-
def get_filename(file_id):
143-
return platform.node() + get_filename_suffix(file_id)
144-
145-
146132
def main():
147133
arg_parser = ArgumentParser(description='monitor processes')
148134
arg_parser.add_argument('--pid', type=int, help='parent process ID ot monitor')
@@ -152,33 +138,32 @@ def main():
152138
arg_parser.add_argument('--affinity', action='store_true',
153139
help='monitor process affinity')
154140
arg_parser.add_argument('--files', action='store_true', help='monitor poen files')
155-
output_group = arg_parser.add_mutually_exclusive_group()
156-
output_group.add_argument('--output-file', help='name of file to store informatoin')
157-
output_group.add_argument('--stdout', action='store_true',
158-
help='output to standard output')
159-
output_group.add_argument('--file_id', help='identification string for output filename')
141+
arg_parser.add_argument('--ancestor', action='store_true',
142+
help='search for ancestor owned by use and report on all its decendants')
143+
arg_parser.add_argument('--output-file', help='name of file to store informatoin')
160144
options = arg_parser.parse_args()
161-
ancestor = find_ancestor(options.pid, options.user)
145+
if options.ancestor:
146+
process = find_ancestor(options.pid, options.user)
147+
else:
148+
process = psutil.Process(options.pid)
162149
inactive = []
163150
if not options.affinity:
164151
inactive.append('affinity')
165152
if not options.files:
166153
inactive.append('read_files')
167154
inactive.append('write_files')
168155
metrics = define_actions(inactive)
169-
if options.stdout:
170-
file = sys.stdout
171-
elif options.output_file:
156+
if options.output_file:
172157
file = open(options.output_file, 'w')
173158
else:
174-
file = open(get_filename(options.file_id), 'w')
159+
file = sys.stdout
175160
try:
176161
with file:
177162
print(status_header(metrics), file=file)
178163
while True:
179-
process_info = [process_status(ancestor, metrics)]
180-
for process in ancestor.children(recursive=True):
181-
process_info.append(process_status(process, metrics))
164+
process_info = [process_status(process, metrics)]
165+
for child_process in process.children(recursive=True):
166+
process_info.append(process_status(child_process, metrics))
182167
print('\n'.join(process_info), file=file)
183168
time.sleep(options.delta)
184169
except KeyboardInterrupt:

Diff for: source-code/subprocess/README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@ The exit code can also be retrieved.
88

99
## What is it?
1010

11-
`wc_metrics.py`: this script computes the number of characters, words, and
12-
lines in a file using the shell's `wc` commaand.
11+
1. `wc_metrics.py`: this script computes the number of characters, words, and
12+
lines in a file using the shell's `wc` commaand.
13+
1. `async_handling.py`: this script illustrates how to monitor the standard error
14+
generated by a subprocess.
15+
1. `process.sh`: Bash script to execute by `async_handling.py`.

Diff for: source-code/subprocess/async_handling.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env python
2+
3+
from datetime import datetime
4+
import subprocess
5+
import sys
6+
import time
7+
8+
class Result:
9+
10+
def set(self, value):
11+
self._value = value
12+
13+
@property
14+
def value(self):
15+
return self._value
16+
17+
18+
def execute(cmd, result):
19+
process = subprocess.Popen(cmd,
20+
stdout=subprocess.PIPE,
21+
stderr=subprocess.PIPE,
22+
text=True)
23+
for stderr_line in iter(process.stderr.readline, ''):
24+
yield stderr_line.strip()
25+
stdout, stderr = process.communicate()
26+
return_code = process.wait()
27+
if return_code:
28+
raise subprocess.CalledProcessError(return_code, cmd)
29+
else:
30+
result.set(stdout)
31+
32+
result = Result()
33+
for stderr_line in execute(['bash', 'process.sh'], result):
34+
print(f'{datetime.now()}: {stderr_line}')
35+
print(f'result:\n{result.value}')

Diff for: source-code/subprocess/process.sh

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
3+
for i in {1..4}
4+
do
5+
(>&2 echo "### info: $i in progress...")
6+
sleep 5
7+
echo "item $i: $((i**2))"
8+
done

0 commit comments

Comments
 (0)