Question
We are simply trying to launch opencode in the background via Python subprocess.Popen, and the execution hands indefinitely at the process.readline() moment. For clarity, this is the standard, very common, way to launch a subprocess (or opencode turn) into the command line from within Python, and yet there are a number of well-known peculiarities in Python between the process.readline() hanging indefinitely when new lines and empty byte strings are not encountered, potentially when the underlying command line process does something peculiar with its handling of newlines etc. I searched the opencode GitHub issues and found only one mention of subprocess.Popen (which really surprises me given how procedurally common this is a requirement to run from Python) so I figured it might be helpful for everyone others to debug this issue here.
This command works as intended when run directly from the command line in about 10 seconds, returning its first json formatted line (type=step_start) within about 7 seconds. All pretty common and in line with TUI expectations.
The use of --format json does not impact the situation, nor does simpler prompts, nor do prompts without files.
The replacement of cmd with trivial or simple cmds (e.g. `cmd=["echo", ""hello""] all work as expected with no issues.
I have searched my code repositories for how I have approached this the few times I remember this being an issue, and most of my implementations elsewhere are more or less identical, so I do not know what the issue is.
Do you?
cmd = ["opencode", "run", "\"Please complete the task using @test_TASK.md @test_PROJECT.md\"" "-f" "test_TASK.md" "-f" "test_PROJECT.md" "--format" "json"]
env = os.environ.copy()
proc = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while self.proc.poll() is None:
# stdout, stderr = self.proc.communicate() # tried this too
for stream, is_error in [(self.proc.stdout, False), (self.proc.stderr, True)]:
if stream and not stream.closed:
try:
line = stream.readline() # <== HANGS HERE INDEFINITELY ON FIRST READ
if line:
line = line.decode("utf-8", errors="replace").rstrip()
except: pass
🔧 Executing command:
opencode run "Please complete the task using @test_TASK.md @test_PROJECT.md" -f test_TASK.md -f test_PROJECT.md --format json
📝 Process 19836 started at 23:28:12
❤️ Heartbeat monitoring active (every 5 seconds)
️❤️ Heartbeat now=23:28:12 +0m 0s pid=19836 state=running_waiting
️❤️ Heartbeat now=23:28:17 +0m 5s pid=19836 state=running_waiting
️❤️ Heartbeat now=23:28:22 +0m10s pid=19836 state=running_waiting
️❤️ Heartbeat now=23:28:27 +0m15s pid=19836 state=running_waiting
️❤️ Heartbeat now=23:28:32 +0m20s pid=19836 state=running_waiting
️❤️ Heartbeat now=23:28:37 +0m25s pid=19836 state=running_waiting
️❤️ Heartbeat now=23:28:42 +0m30s pid=19836 state=running_waiting
️❤️ Heartbeat now=23:28:47 +0m35s pid=19836 state=running_waiting
️❤️ Heartbeat now=23:28:52 +0m40s pid=19836 state=running_waiting
Question
We are simply trying to launch opencode in the background via Python subprocess.Popen, and the execution hands indefinitely at the process.readline() moment. For clarity, this is the standard, very common, way to launch a subprocess (or opencode turn) into the command line from within Python, and yet there are a number of well-known peculiarities in Python between the process.readline() hanging indefinitely when new lines and empty byte strings are not encountered, potentially when the underlying command line process does something peculiar with its handling of newlines etc. I searched the opencode GitHub issues and found only one mention of
subprocess.Popen(which really surprises me given how procedurally common this is a requirement to run from Python) so I figured it might be helpful for everyone others to debug this issue here.This command works as intended when run directly from the command line in about 10 seconds, returning its first json formatted line (type=step_start) within about 7 seconds. All pretty common and in line with TUI expectations.
The use of
--format jsondoes not impact the situation, nor does simpler prompts, nor do prompts without files.The replacement of cmd with trivial or simple cmds (e.g. `cmd=["echo", ""hello""] all work as expected with no issues.
I have searched my code repositories for how I have approached this the few times I remember this being an issue, and most of my implementations elsewhere are more or less identical, so I do not know what the issue is.
Do you?