Skip to content

Commit 70ef45e

Browse files
committed
Add stream_output option to get_output_from_qchem function
1 parent ad114ae commit 70ef45e

2 files changed

Lines changed: 23 additions & 56 deletions

File tree

pyqchem/errors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def __str__(self):
1111
class OutputError(Exception):
1212
def __init__(self, output, error_output):
1313
self.full_output = output
14-
self.error_lines = error_output + '\n'.join(output.split('\n')[-20:])
14+
self.error_lines = '\n'.join(output.split('\n')[-20:]) + error_output
1515

1616
def __str__(self):
1717
return 'Error in Q-Chem calculation:\n{}'.format(self.error_lines)

pyqchem/qchem_core.py

Lines changed: 22 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from pyqchem.qc_input import QchemInput
22
from pyqchem.errors import ParserError, OutputError
33
from pyqchem.utils import get_sdm
4-
from subprocess import Popen, PIPE
4+
from subprocess import Popen, PIPE, STDOUT
55
from pathlib import Path
66
import os, shutil, sys
77
import numpy as np
@@ -164,15 +164,15 @@ def func_wrapper(*args, **kwargs):
164164
return func_wrapper
165165

166166

167-
def local_run(input_file_name, work_dir, fchk_file, use_mpi=False, processors=1):
167+
def local_run(input_file_name, work_dir, fchk_file, use_mpi=False, processors=1, stream_output=False):
168168
"""
169169
Run Q-Chem locally
170170
171171
:param input_file_name: Q-Chem input file in plain text format
172172
:param work_dir: Scratch directory where calculation run
173173
:param fchk_file: filename of fchk
174174
:param use_mpi: use mpi instead of openmp
175-
175+
:param stream_output: print Q-Chem output live during execution
176176
:return: output, err: Q-Chem standard output and standard error
177177
"""
178178

@@ -188,57 +188,20 @@ def local_run(input_file_name, work_dir, fchk_file, use_mpi=False, processors=1)
188188
binary = Path(qc_dir).joinpath(exe_dir).joinpath('qcprog.exe')
189189
command = [binary, Path(work_dir).joinpath(input_file_name), Path(work_dir)]
190190

191-
qchem_process = Popen(command, stdout=PIPE, stdin=PIPE, stderr=PIPE, cwd=work_dir)
192-
(output, err) = qchem_process.communicate()
193-
qchem_process.wait()
194-
output = output.decode(errors='ignore')
195-
err = err.decode()
196-
197-
return output, err
198-
199-
def local_run_stream(input_file_name, work_dir, fchk_file, use_mpi=False, processors=1, print_stream=True):
200-
"""
201-
Run Q-Chem locally
202-
203-
:param input_file_name: Q-Chem input file in plain text format
204-
:param work_dir: Scratch directory where calculation run
205-
:param fchk_file: filename of fchk
206-
:param use_mpi: use mpi instead of openmp
207-
:param print_stream: set True to print output stream during execution
208-
209-
:return: output, err: Q-Chem standard output and standard error
210-
"""
211-
212-
if not use_mpi:
213-
os.environ["QCTHREADS"] = "{}".format(processors)
214-
os.environ["OMP_NUM_THREADS"] = "{}".format(processors)
215-
os.environ["MKL_NUM_THREADS"] = "1"
216-
217-
os.environ["GUIFILE"] = fchk_file
218-
qc_dir = os.getenv('QC')
219-
220-
exe_dir = os.getenv('QC_EXE_DIR') if 'QC_EXE_DIR' in os.environ else 'exe'
221-
binary = Path(qc_dir).joinpath(exe_dir).joinpath('qcprog.exe')
222-
command = [binary, Path(work_dir).joinpath(input_file_name), Path(work_dir)]
223-
224-
qchem_process = Popen(command, stdout=PIPE, stdin=PIPE, stderr=PIPE, cwd=work_dir)
225-
226-
output = ''
227-
err = ''
228-
while True:
229-
line_out = qchem_process.stdout.readline()
230-
line_err = qchem_process.stderr.readline()
231-
232-
if not line_out and not line_err:
233-
break
234-
235-
if print_stream:
236-
print(line_out.strip().decode(errors='ignore'))
237-
238-
sys.stdout.flush()
239-
240-
output += line_out.decode(errors='ignore')
241-
err += line_err.decode(errors='ignore')
191+
if stream_output:
192+
qchem_process = Popen(command, stdout=PIPE, stdin=PIPE, stderr=STDOUT, cwd=work_dir, text=True, bufsize=1)
193+
output = ''
194+
err = ''
195+
for line_out in qchem_process.stdout:
196+
print(line_out, end='') # Print output as generated
197+
output += line_out
198+
qchem_process.wait()
199+
else:
200+
qchem_process = Popen(command, stdout=PIPE, stdin=PIPE, stderr=PIPE, cwd=work_dir)
201+
(output, err) = qchem_process.communicate()
202+
qchem_process.wait()
203+
output = output.decode(errors='ignore')
204+
err = err.decode()
242205

243206
return output, err
244207

@@ -359,6 +322,7 @@ def retrieve_additional_files(input_qchem, data_fchk, work_dir, scratch_read_lev
359322
:param data_fchk: FCHK parsed dictionary
360323
:param work_dir: scratch directory
361324
:param scratch_read_level: defines what data to retrieve
325+
362326
:return: dictionary with additional data
363327
"""
364328

@@ -487,6 +451,7 @@ def get_output_from_qchem(input_qchem,
487451
fchk_only=False,
488452
store_full_output=False,
489453
delete_scratch=True,
454+
stream_output=False,
490455
remote=None,
491456
scratch_read_level=0):
492457

@@ -514,6 +479,7 @@ def get_output_from_qchem(input_qchem,
514479
:param remote: dictionary containing the data for remote calculation (beta)
515480
:param store_full_output: store full output in plain text in pkl file
516481
:param delete_scratch: delete all scratch files when calculation is finished
482+
:param stream_output: print Q-Chem output live during execution
517483
518484
:return: output [, electronic_structure]
519485
"""
@@ -587,7 +553,8 @@ def get_output_from_qchem(input_qchem,
587553
if output is None or force_recalculation is True:
588554
if remote is None:
589555
# print('local:')
590-
output, err = local_run(temp_filename, work_dir, fchk_filename, use_mpi=use_mpi, processors=processors)
556+
output, err = local_run(temp_filename, work_dir, fchk_filename,
557+
use_mpi=use_mpi, processors=processors, stream_output=stream_output)
591558
else:
592559
# print('Remote:')
593560
output, err = remote_run(temp_filename, work_dir, fchk_filename, remote, use_mpi=use_mpi, processors=processors)

0 commit comments

Comments
 (0)