3from AthenaCommon
import Logging
4from .non_blocking_stream_reader
import NonBlockingStreamReader
8logger = Logging.logging.getLogger(
"PowhegControl")
12 """! Wrapper to handle multiple Powheg subprocesses.
14 @author James Robinson <james.robinson@cern.ch>
20 @param process_list List of processes to manage.
26 """! Monitor each of the managed processes and log when they are finished."""
28 process.id_number = idx + 1
31 if not process.has_output():
32 _return_code = process.return_code
35 logger.info(
"Finished process #{}: there are now {}/{} running".format(process.id_number, len(self.
__process_list), self.
__n_initial))
37 logger.warning(
"Process #{} terminated unexpectedly (return code {}): there are now {}/{} running".format(process.id_number, _return_code, len(self.
__process_list), self.
__n_initial))
41 """! Single executable running in a subprocess (usually PowhegBox).
43 @author James Robinson <james.robinson@cern.ch>
46 log_level = {
"stdout":
"info",
"stderr":
"error"}
47 __output_prefix =
" | "
50 def __init__(self, command_list, seed_index=None, stdin=None, ignore_output=None, warning_output=[], info_output=[], error_output=[]):
53 Setup underlying process together with non-blocking readers for stdout and stderr.
55 @param command_list Command that will be run (possibly with options).
56 @param seed_index Which seed from pwgseeds.dat to use.
57 @param stdin An open file handle providing input.
58 @param ignore_output List of strings to filter out from messages.
59 @param warning_output List of strings which would always trigger a warning only, even if produced in stderr.
60 @param info_output List of strings which would always trigger an info only, even if produced in stderr.
61 @param error_output List of strings which would always trigger an error, even if produced in stdout.
63 if not isinstance(command_list, list):
64 command_list = [command_list]
65 command_list = [str(x)
for x
in command_list]
67 if ignore_output
is not None:
75 self.
__process = subprocess.Popen(command_list, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, text=
True)
77 if seed_index
is not None:
79 self.
__process.stdin.write(str(seed_index))
81 with open(
"pwgseeds.dat",
"r")
as seed_file:
82 random_seed_list = seed_file.read().splitlines()
83 self.
log(
"Providing random seed: {}".format(random_seed_list[seed_index - 1]))
86 self.
__process = subprocess.Popen(command_list, stdout=subprocess.PIPE, stdin=stdin, stderr=subprocess.PIPE, text=
True)
94 """! Write queued output and return process status."""
100 """! Check if the underlying process is running and finalise stream readers if not."""
102 for nbsr
in (
"stdout",
"stderr"):
103 getattr(self, nbsr).finalise()
107 def log(self, message, log_level="info"):
108 """! Write to the logger with appropriate log-level.
110 @param message The message to pass to the logger.
111 @param log_level Which level to log at.
114 while word
in message:
115 message = message.replace(word,
"")
116 getattr(logger, log_level)(
"{}{}".format(self.
__output_prefix, message.strip()))
119 """! Pass queued output to the logger."""
120 for stream
in [
"stdout",
"stderr"]:
122 output, queue_size = getattr(self, stream).readline(timeout=0.1)
123 if output
is not None and any([(pattern
in output)
for pattern
in self.
__error_output]):
124 self.
log(output,
"error")
125 elif output
is not None and any([(pattern
in output)
for pattern
in self.
__warning_output]):
126 self.
log(output,
"warning")
127 elif output
is not None and any([(pattern
in output)
for pattern
in self.
__info_output]):
128 self.
log(output,
"info")
129 elif not (output
is None or len(output) == 0):
136 """! Return code of underlying process."""
141 """! stdout stream from underlying process."""
146 """! stderr stream from underlying process."""
Read an output stream without blocking.
Wrapper to handle multiple Powheg subprocesses.
monitor(self)
Monitor each of the managed processes and log when they are finished.
__init__(self, process_list)
Constructor.
Single executable running in a subprocess (usually PowhegBox).
__init__(self, command_list, seed_index=None, stdin=None, ignore_output=None, warning_output=[], info_output=[], error_output=[])
Constructor.
log(self, message, log_level="info")
Write to the logger with appropriate log-level.
stdout(self)
stdout stream from underlying process.
has_output(self)
Write queued output and return process status.
return_code(self)
Return code of underlying process.
write_queued_output(self)
Pass queued output to the logger.
stderr(self)
stderr stream from underlying process.
is_running(self)
Check if the underlying process is running and finalise stream readers if not.