SyntaxError: unterminated string literal when using \n in string with pyodide.runPython()
🐛 Bug
When using pyodide.runPython() with a string containing a \n newline character inside a Python string literal, a SyntaxError: unterminated string literal is thrown, even though the string is properly terminated.
To Reproduce
<!doctype html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/pyodide/v0.29.0/full/pyodide.js"></script>
</head>
<body>
<script type="text/javascript">
async function main(){
let pyodide = await loadPyodide();
pyodide.runPython("print('hello\nworld')");
}
main();
</script>
</body>
</html>
Expected behavior
The code should execute without errors and print:
hello
world
Environment
- Pyodide Version: 0.29.0
- Browser version: 135.0.7049.72
- Any other relevant information: The error occurs when a newline escape sequence (
\n) is included inside a single-quoted Python string passed torunPython().
Additional context
The error message indicates that the Python parser detects an unterminated string literal at the line containing print('hello, suggesting that the \n escape sequence is being interpreted as a literal newline in the Python source code rather than a string escape, causing the string to be split across lines and appear unterminated.
I found that If I change \n to \n for the code, it compile successfully. I'm not sure if this aligns with the design expectations?
pyodide.runPython("print('hello\nworld')"); // ❌ SyntaxError: unterminated string literal
pyodide.runPython("print('hello\\nworld')"); // ✅
Thanks for the report.
We use eval internally to run the Python code, and the minimal reproducer, which shows the same error in local Python as well, would be
eval("print('hello\nworld')")
I guess we'll need to escape the user input string before passing it to eval.
Actually, I think this is not easy to fix. We cannot distinguish if the \n newline character is used inside the string or if it is used for actually separating the Python statements.
For example, if the user passes something like pyodide.runPython("print(1)\nprint(2)"), the \n should actually work as a newline character that separates the print statements.