pyodide icon indicating copy to clipboard operation
pyodide copied to clipboard

SyntaxError: unterminated string literal when using \n in string with pyodide.runPython()

Open cnzhujie opened this issue 2 months ago • 3 comments

🐛 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 to runPython().

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.

cnzhujie avatar Nov 12 '25 05:11 cnzhujie

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')"); // ✅ 

cnzhujie avatar Nov 12 '25 05:11 cnzhujie

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.

ryanking13 avatar Nov 12 '25 07:11 ryanking13

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.

ryanking13 avatar Nov 12 '25 08:11 ryanking13