-
Notifications
You must be signed in to change notification settings - Fork 35
feat: add streaming output for dp train #307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,4 +1,7 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import os | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import subprocess | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import sys | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import threading | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from typing import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
List, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Tuple, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -11,6 +14,74 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from dflow.utils import run_command as dflow_run_command | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def run_command_streaming( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cmd: Union[str, List[str]], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
shell: bool = False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
log_file=None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) -> Tuple[int, str, str]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Run command with streaming output to both terminal and log file.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(cmd, str): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cmd = cmd if shell else cmd.split() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Open log file if specified | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
log_fp = open(log_file, "w") if log_file else None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Start subprocess | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
process = subprocess.Popen( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cmd, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stdout=subprocess.PIPE, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stderr=subprocess.PIPE, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stdin=subprocess.PIPE, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
shell=shell, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
text=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bufsize=1, # Line buffered | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
universal_newlines=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Store output | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stdout_buffer = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stderr_buffer = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def stream_output(pipe, buffer, is_stderr=False): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for line in iter(pipe.readline, ""): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buffer.append(line) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Print to terminal | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if is_stderr: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
print(line, end="", file=sys.stderr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
print(line, end="") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Write to log file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if log_fp: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
log_fp.write(line) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
log_fp.flush() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pipe.close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+42
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard concurrent writes to the same log file
# Store output
stdout_buffer = []
stderr_buffer = []
+ log_lock = threading.Lock() if log_fp else None
def stream_output(pipe, buffer, is_stderr=False):
for line in iter(pipe.readline, ""):
buffer.append(line)
# Print to terminal
if is_stderr:
print(line, end="", file=sys.stderr)
else:
print(line, end="")
# Write to log file
if log_fp:
- log_fp.write(line)
- log_fp.flush()
+ with log_lock:
+ log_fp.write(line)
+ log_fp.flush()
pipe.close() 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Start threads for streaming | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stdout_thread = threading.Thread( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
target=stream_output, args=(process.stdout, stdout_buffer, False) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stderr_thread = threading.Thread( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
target=stream_output, args=(process.stderr, stderr_buffer, True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stdout_thread.start() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stderr_thread.start() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Wait for process to complete | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return_code = process.wait() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Wait for threads to finish | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stdout_thread.join() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stderr_thread.join() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return return_code, "".join(stdout_buffer), "".join(stderr_buffer) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
finally: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if log_fp: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
log_fp.close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def run_command( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cmd: Union[str, List[str]], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
shell: bool = False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use shlex for robust splitting and handle shell=True with list commands
cmd.split()
breaks on quoted args and spaces; also, passing a list whileshell=True
is unsupported/undefined. Prefershlex.split
andshlex.join
to cover both cases safely.📝 Committable suggestion
🤖 Prompt for AI Agents