On Windows, create_subprocess_shell re-escapes quotes inside the command, so
anything with double quotes reaches the child corrupted. The same command works on
the stdlib asyncio loop and on uvloop (Linux).
This commonly breaks python -c commands.
I feel like this was intentionally left. I would love to know the reasoning if it was.
Reproduce Bug
import asyncio
import winloop
CMD = 'python -c "import sys; print(\\"hi\\")"'
async def run_shell():
proc = await asyncio.create_subprocess_shell(
CMD,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
out, err = await proc.communicate()
return out, err, proc.returncode
print("asyncio:", asyncio.run(run_shell()))
loop = winloop.new_event_loop()
asyncio.set_event_loop(loop)
try:
print("winloop:", loop.run_until_complete(run_shell()))
finally:
loop.close()
Result
asyncio: (b'hi\r\n', b'', 0)
winloop: (b'', b' File "<string>", line 1\r\n "import\r\n ^\r\nSyntaxError: unterminated string literal (detected at line 1)\r\n', 1)
- asyncio prints
hi (rc 0)
- winloop gets a corrupted
-c argument and fails with SyntaxError: unterminated string literal (rc 1)
- simpler commands like python -c with a quoted print silently produce empty output instead
I ran into this while building an agentic AI app. The agent often generates shell
commands like python -c with quoted code strings, and those almost always include
quotes. With winloop (through uvicorn) those commands fail or produce no output.
The same commands work fine with the stdlib asyncio loop.
Root cause
Winloop passes the shell command to cmd.exe as separate arguments, and libuv
re-escapes the quotes. asyncio builds one command string (cmd.exe /c plus the
full command wrapped in quotes) instead, so the quotes are not mangled.
Environment
- winloop: 0.6.3
- Python: 3.13.13
- Windows: 11
On Windows,
create_subprocess_shellre-escapes quotes inside the command, soanything with double quotes reaches the child corrupted. The same command works on
the stdlib asyncio loop and on uvloop (Linux).
This commonly breaks python -c commands.I feel like this was intentionally left. I would love to know the reasoning if it was.
Reproduce Bug
Result
hi(rc 0)-cargument and fails withSyntaxError: unterminated string literal(rc 1)I ran into this while building an agentic AI app. The agent often generates shell
commands like python -c with quoted code strings, and those almost always include
quotes. With winloop (through uvicorn) those commands fail or produce no output.
The same commands work fine with the stdlib asyncio loop.
Root cause
Winloop passes the shell command to cmd.exe as separate arguments, and libuv
re-escapes the quotes. asyncio builds one command string (cmd.exe /c plus the
full command wrapped in quotes) instead, so the quotes are not mangled.
Environment