googlecolab / colabtools

Python libraries for Google Colaboratory
Apache License 2.0
2.2k stars 722 forks source link

Calling asyncio.run() from a running event loop #3720

Open bilan604 opened 1 year ago

bilan604 commented 1 year ago

Describe the current behavior In a Python code cell on the colab notebook, when a line attempts to use asyncio.run(function()), the error message says that "asyncio.run() cannot be called from a running event loop". Nor can main.py files containing asyncio.run(main()) be imported from google drive, (when there is no if case for name == __main)

Colab notebooks and allow Python files containing asyncio.run() to be executed via command, but since in Colab Notebooks chunk cells you can set python variables with command line executions, non-async python functions can execute asyncio.run() tasks.

Describe the expected behavior Trying to run asyncio.run() is supposed to raise an error in a Colab notebook when running a Python code cell. Trying to run asyncio.run() is also supposed to raise an error when called within asyncio.run(). This is essentially command injection.

What web browser you are using Google Chrome

Additional context Link To Colab Notebook documenting the issue: https://colab.research.google.com/drive/1jInO_0I0CwvVHYBbnKbNo74ZUznGbAEQ?usp=sharing

EvanWiederspan commented 1 year ago

In Colab, you'll need to get a handle of the current running loop first. The following snippet should work:

import asyncio

async def main():
    print("main() function called")
    return "response"

loop = asyncio.get_running_loop()
await loop.create_task(main())

See this other issue as well, https://github.com/googlecolab/colabtools/issues/1648

bilan604 commented 1 year ago

In Colab, you'll need to get a handle of the current running loop first. The following snippet should work:

import asyncio

async def main():
    print("main() function called")
    return "response"

loop = asyncio.get_running_loop()
await loop.create_task(main())

See this other issue as well, #1648

Yes, I am aware that is the following is the intended behavior when running an async function in colab:

await asyncio.create_task(task())

The bug is that I am able to run asyncio.run() in colab, which should not be allowed. In Python in general, asyncio.run() should not be callable in the same thread as one called by asyncio.run(). Since I describe a way to do it, there might be a way to permanently stall the parent process that called the overhead asyncio.run() call, instead of the notebook timing out. Try running this code that does nothing but stall a cell:

import os
import asyncio

s = """
import asyncio

async def main():
    print("main() function called")
    for i in range(120000):
        await asyncio.sleep(40000)
    return "response"

asyncio.run(main())

"""

with open("cache.txt", "w+") as f:
    for line in s.split("\n"):
        f.write(line+"\n")

with open("cache.txt", "rb") as f:
    lines = f.readlines()

with open("newPythonFile.py", "wb") as f:
    for line in lines:
        f.write(line)

with open("newPythonFile.py", "wb") as f:
    for line in lines:
        f.write(line)

def run_main():
    response = !python3 newPythonFile.py
    return response

run_main()