I'm using aiohttp as server and telethon client for sending messages.
Running this edited code from telegrammodule.py is working fine:
from telethon import TelegramClient
import asyncio
api_id = censored
api_hash = "censored"
client = TelegramClient('anon', api_id, api_hash)
async def sendMessageToUser(user, message):
await client.send_message(user, message)
def sendMessage(user, message):
with client:
client.loop.run_until_complete(sendMessageToUser(user, message))
sendMessage("censored", "Hello")
This is the error I get when I try to call the function sendMessage() from server.py:
======== Running on http://0.0.0.0:5000 ========
(Press CTRL+C to quit)
Error handling request
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/aiohttp/web_protocol.py", line 418, in start
resp = await task
File "/usr/local/lib/python3.7/dist-packages/aiohttp/web_app.py", line 458, in _handle
resp = await handler(request)
File "server.py", line 9, in send
response = await sendMessage(user, message)
File "/home/user/telegram_user_bot/telegrammodule.py", line 13, in sendMessage
client.loop.run_until_complete(sendMessageToUser(user, message))
File "/usr/lib/python3.7/asyncio/base_events.py", line 571, in run_until_complete
self.run_forever()
File "/usr/lib/python3.7/asyncio/base_events.py", line 526, in run_forever
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
Task exception was never retrieved
future: <Task finished coro=<sendMessageToUser() done, defined at /home/user/telegram_user_bot/telegrammodule.py:8> exception=ConnectionError('Cannot send requests while disconnected')>
Traceback (most recent call last):
File "/home/user/telegram_user_bot/telegrammodule.py", line 9, in sendMessageToUser
await client.send_message(user, message)
File "/usr/local/lib/python3.7/dist-packages/telethon/client/messages.py", line 752, in send_message
result = await self(request)
File "/usr/local/lib/python3.7/dist-packages/telethon/client/users.py", line 53, in __call__
future = self._sender.send(request, ordered=ordered)
File "/usr/local/lib/python3.7/dist-packages/telethon/network/mtprotosender.py", line 170, in send
raise ConnectionError('Cannot send requests while disconnected')
ConnectionError: Cannot send requests while disconnected
Here's the code from server.py:
from telegrammodule import sendMessage
from aiohttp import web
import asyncio
async def send(request):
data = await request.post()
user = data['user']
message = data['message']
response = await sendMessage(user, message)
app = web.Application()
app.router.add_post("/send", send)
if __name__ == "__main__":
web.run_app(app, port=5000)
And here from telegrammodule.py:
from telethon import TelegramClient
import asyncio
api_id = censored
api_hash = "censored"
client = TelegramClient('anon', api_id, api_hash)
async def sendMessageToUser(user, message):
await client.send_message(user, message)
async def sendMessage(user, message):
async with client:
client.loop.run_until_complete(sendMessageToUser(user, message))
I don't know how to solve the problem. How can I fix it?
If a loop is already running, you can't start it one more time. Use create_task, to add a task to a running loop.
For your case
client.loop.create_task(sendMessageToUser(user, message))
would be a fix, I guess.
Also, if the client.loop is in another thread, you might use run_coroutine_threadsafe:
asyncio.run_coroutine_threadsafe(sendMessageToUser(user, message), client.loop)
And one more important thing - if client.loop is the loop you're currently in, you can await sendMessageToUser(user, message) until message is sent.
Related
I have a Python server that needs to upgrade an existing connection to TLS. The connection is created by asyncio.start_server.
It needs to upgrade to TLS in the middle of a connection because it is emulating MySQL's wire protocol.
The project is mysql-mimic. Here is what I've tried so far: https://github.com/kelsin/mysql-mimic/pull/17
There appears to be a some kind of sequencing issue: if the client starts TLS before the server, the server never completes the handshake.
Here is a script to reproduce the issue:
import asyncio
import ssl
# Self-signed certs for testing
CERT_FILE = "cert.pem"
CERT = """
-----BEGIN CERTIFICATE-----
MIIEIzCCAwugAwIBAgIUUMROPFb3ZMssWfl9/tJVMB0Zl0owDQYJKoZIhvcNAQEL
BQAwgZ8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
DA1TYW4gRnJhbmNpc2NvMRQwEgYDVQQKDAtteXNxbC1taW1pYzEUMBIGA1UECwwL
bXlzcWwtbWltaWMxFDASBgNVBAMMC215c3FsLW1pbWljMSEwHwYJKoZIhvcNAQkB
FhJleGFtcGxlQGRvbWFpbi5jb20wIBcNMjIxMDI0MTgyNzQ0WhgPMjEyMjA5MzAx
ODI3NDRaMIGfMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG
A1UEBwwNU2FuIEZyYW5jaXNjbzEUMBIGA1UECgwLbXlzcWwtbWltaWMxFDASBgNV
BAsMC215c3FsLW1pbWljMRQwEgYDVQQDDAtteXNxbC1taW1pYzEhMB8GCSqGSIb3
DQEJARYSZXhhbXBsZUBkb21haW4uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAsnmS0k1Q0f+mv7izbT5K8zqYP54KwyW000qMhYLW/Ir5fGAw2QHg
Q1vMBY+1oaHcO1DxjriG4l8P8ho9AShAD63Q3PVUiy3Prxi3PaZ/jPsI5rN/8s7s
TXai6Po6gD56uYtZACl4cjF2ob3Vy/qzIPitW3D7UVEL+nqDEZUSmbFnT+NAMaCv
Bq+Zf94vQSpQXgUSbTNAuFqjwMLeb8VX31e5yFOvhRd1Y65MOwmeCX0hMZ+XtcPc
xtgCyQ9uT2OaKcqcngE/LtGnC4UJy0u5bcI8pPgwenGWNhQ6LrqLWAUizEXoprY8
PUVoE42Itm7j1ODKm71OpNPqEjXxvs924wIDAQABo1MwUTAdBgNVHQ4EFgQUSVIG
PQ1FTdvJeup85cCLpp/5wGIwHwYDVR0jBBgwFoAUSVIGPQ1FTdvJeup85cCLpp/5
wGIwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAJcoALjwItgWa
Qpr/hJCHhtf1gS6DCbtQoc+Owvz0iJkC+zqeaFlOYwVQz/n8iQ45g03cLMxHfMEv
lj1ctHfVGI+2exp2hesMmU+CT49D9qFS2vQnaKxkeUqv5ia2d+V49jE6fj3CxIPP
T3yI9+K2Ojx+7/WVVxCgz+eIZJbTCugoypDksldfuY4mx48E9qefOlBNcYyBzHt4
4iymCFFrfQHfMX+PnKDGHaoh/T/oZxdZRyDxNqTLfiyZ1PtAbueeT4Jf6CmamQZh
IadFPXnA1YlEqreMk6nDrF8pqgOosHIngLhhUXHAVj/Br3UaDTaUGzlrlL7rLpRL
oToCkplUgg==
-----END CERTIFICATE-----
"""
KEY_FILE = "key.pem"
KEY = """
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCyeZLSTVDR/6a/
uLNtPkrzOpg/ngrDJbTTSoyFgtb8ivl8YDDZAeBDW8wFj7Whodw7UPGOuIbiXw/y
Gj0BKEAPrdDc9VSLLc+vGLc9pn+M+wjms3/yzuxNdqLo+jqAPnq5i1kAKXhyMXah
vdXL+rMg+K1bcPtRUQv6eoMRlRKZsWdP40AxoK8Gr5l/3i9BKlBeBRJtM0C4WqPA
wt5vxVffV7nIU6+FF3Vjrkw7CZ4JfSExn5e1w9zG2ALJD25PY5opypyeAT8u0acL
hQnLS7ltwjyk+DB6cZY2FDouuotYBSLMReimtjw9RWgTjYi2buPU4MqbvU6k0+oS
NfG+z3bjAgMBAAECggEBAI1wPUO+k/soUByGImPDxyAE4p0gAUVv/2KnJL+11exj
sp23mV6Q1wpqmEAcCIQkQuUbG6PQZszFK1zhIFFndYU3aVuCbNKzpnAL9UO9TD4M
v5wcypxBEhG9oBNkIrJ5UUbzwL+ZHePZgTtitykk74qEqNXbrr9drFF/f5mSeyAi
nUkizI/aGJVp2+NVpsFvZd0M5gM1tEWoBq/5fny/b1oWM/blh1ZwWQII3bTcDABH
1h30oTuGWYyeQExUjiS4SDDJ8BH9PZxUGQhQsK1ZuJczJ5B+jh0OWicdD+P+V2EB
npoWQVHKwqwfDQisx2T04TAb65QcbM7V/EwgQPpcd5ECgYEA3bQbff5bIvbgJwCo
1bHxj3MMmu1Qs+Km9nR8FbEtFaF1lbXzPLCj98VDpT3tBNw4VwpbVYn5rd4ZSs6h
jlK2zEakFRvU/qgtTrUviW4oeSrEtUt8jI0QkdobUWPM8HuZih6Lgm5DTU6HwIBR
dxkhojx7c1zwSm66Bojvn/CjVakCgYEAzhWHAxkNAj97XvjUe9XsV41jiksheNS2
7vAm1PASq9MGFpSazq2NeXTxuChvMK8vN9r2FngnFKW4hLGMi8wpReT+S1C32sNP
ZWRq6w2JWgQvh7dNSNmn0mBc7zwUB6sFeS72q3Ge355dPJiuomRLxZmm+P3suHIV
b+4Fj6q0p6sCgYEAqj5EojJwn1+97pVGEJqM6N+qvUkgoJGaLkRyiGG+Qg7y8RyA
BImLz5ZuBHSSDhphNQ1h50SFMusKtvQHAPgpIKHaG898dnSEHh1pvHmXoLujw6eM
o40rPSSjt5MQa1YuJ+6eqHCtQ67a9YpThEYLGr6g+YxThISUWrJKd6HceskCgYB0
gWMUc0MRdEYQyOeHIsc8L+iINDU2FDtfFVE+rIJBtUkJ1vU1xpPmiCBnFiTWBxPQ
pe7dgQvG9nE8QwvLtJ3Yr767YWSvPh9SmNSBEeQGibs9JHmCp9niayve673/H8Y2
XkCBZ/iDPwpCyaZglAbqLRViSltbYtOPtaZbNAxxhQKBgH8Gj0yg3A5DwWEyeUKR
KJBS2rPiKgrhJs8Kd8GZZUb3H5WGqzfgrRK1p9j5Ug8UXSWbB9e5jg4ymVtcAAhc
tRz4rCvYNY8fHlA2TfzrOeEuuxtoMFyxd26eFjZvS/w2VdFrIQZbSvDkV4hMqhpS
CCslSFIIZOMCzqgQtM+NTQJ6
-----END PRIVATE KEY-----
"""
async def start_tls(reader, writer, sslcontext, server_side=False):
# Borrowed from https://stackoverflow.com/questions/62851407/how-do-i-enable-tls-on-an-already-connected-python-asyncio-stream
transport = writer.transport
protocol = transport.get_protocol()
loop = asyncio.get_event_loop()
new_transport = await loop.start_tls(
transport=transport,
protocol=protocol,
sslcontext=sslcontext,
server_side=server_side,
ssl_handshake_timeout=5, # arbitrarily small timeout so the test fails faster
)
reader._transport = new_transport
writer._transport = new_transport
async def server_cb(reader, writer):
# Sleeping 1 second seems to reliably reproduce the error
await asyncio.sleep(1)
sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
sslcontext.load_cert_chain(CERT_FILE, KEY_FILE)
await start_tls(reader, writer, sslcontext, server_side=True)
# We never get here
print(await reader.read(4))
writer.write(b"pong")
await writer.drain()
async def client(reader, writer):
sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
sslcontext.check_hostname = False
sslcontext.verify_mode = ssl.VerifyMode.CERT_NONE
await start_tls(reader, writer, sslcontext, server_side=False)
# We never get here
writer.write(b"ping")
await writer.drain()
print(await reader.read(4))
async def main():
with open(CERT_FILE, "w") as fp:
fp.write(CERT)
with open(KEY_FILE, "w") as fp:
fp.write(KEY)
server = await asyncio.start_server(
client_connected_cb=server_cb,
host="localhost",
port=0, # Let the OS pick an available port
)
task = asyncio.create_task(server.serve_forever())
try:
port = server.sockets[0].getsockname()[1]
reader, writer = await asyncio.open_connection(host="localhost", port=port)
await client(reader, writer)
writer.close()
await writer.wait_closed()
finally:
task.cancel()
asyncio.run(main())
The output:
Task exception was never retrieved
future: <Task finished name='Task-5' coro=<server_cb() done, defined at /Users/barak_alon/Library/Application Support/JetBrains/PyCharmCE2022.2/scratches/tls_race_condition.py:82> exception=ConnectionResetError()>
Traceback (most recent call last):
File "/Users/barak_alon/Library/Application Support/JetBrains/PyCharmCE2022.2/scratches/tls_race_condition.py", line 88, in server_cb
await start_tls(reader, writer, sslcontext, server_side=True)
File "/Users/barak_alon/Library/Application Support/JetBrains/PyCharmCE2022.2/scratches/tls_race_condition.py", line 71, in start_tls
new_transport = await loop.start_tls(
File "/Users/barak_alon/.pyenv/versions/3.9.7/lib/python3.9/asyncio/base_events.py", line 1231, in start_tls
await waiter
ConnectionResetError
Traceback (most recent call last):
File "/Users/barak_alon/Library/Application Support/JetBrains/PyCharmCE2022.2/scratches/tls_race_condition.py", line 129, in <module>
asyncio.run(main())
File "/Users/barak_alon/.pyenv/versions/3.9.7/lib/python3.9/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/Users/barak_alon/.pyenv/versions/3.9.7/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
return future.result()
File "/Users/barak_alon/Library/Application Support/JetBrains/PyCharmCE2022.2/scratches/tls_race_condition.py", line 123, in main
await client(reader, writer)
File "/Users/barak_alon/Library/Application Support/JetBrains/PyCharmCE2022.2/scratches/tls_race_condition.py", line 100, in client
await start_tls(reader, writer, sslcontext, server_side=False)
File "/Users/barak_alon/Library/Application Support/JetBrains/PyCharmCE2022.2/scratches/tls_race_condition.py", line 71, in start_tls
new_transport = await loop.start_tls(
File "/Users/barak_alon/.pyenv/versions/3.9.7/lib/python3.9/asyncio/base_events.py", line 1231, in start_tls
await waiter
ConnectionAbortedError: SSL handshake is taking longer than 5 seconds: aborting the connection
Anyone have any idea what's going on here? Is there a fix that doesn't require a custom asyncio Protocol?
Calling .pause_reading() on the transport before you try to elevate it to TLS might help.
My code is is similar to this example:
import discord
import tweepy
import asyncio
class Client(discord.Client):
async def on_ready(self):
print("ready")
global GUILD
GUILD = discord.utils.get(self.guilds, name = "Any Guild")
class TweepyStream(tweepy.Stream):
def on_connect(self):
print("connceted")
def on_status(self, status):
print(status.text)
channel = discord.utils.get(GUILD.channels, name = "twitter-posts")
asyncio.run(channel.send(status.text))
#From here the Discord message should be send
auth = tweepy.OAuthHandler(keys)
auth.set_access_token(tokens)
global api
api = tweepy.API(auth)
follow_list = []
follow = int(api.get_user(screen_name = "Any User").id)
print(follow)
follow_list.append(follow)
print(str(follow_list))
stream = TweepyStream(tokens and keys)
stream.filter(follow = follow_list, threaded=True) #track = track,
client = Client()
client.run(token)
I try to receive Twitter posts and send them into a Discord channel, but it doesn't work. How can I do this (maybe without asyncio)?
Or is there a way to work with a Python Twitter API, which works with async functions?
My error:
Stream encountered an exception
Traceback (most recent call last):
File "C:\Python39\lib\site-packages\tweepy\streaming.py", line 133, in _connect
self.on_data(line)
File "C:\Python39\lib\site-packages\tweepy\streaming.py", line 387, in on_data
return self.on_status(status)
File "c:\Users\morit\Desktop\FLL 2021 Bot\DiscordBot\DiscordBotV0.7\example.py", line 18, in on_status
asyncio.run(channel.send(status.text))
File "C:\Python39\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "C:\Python39\lib\asyncio\base_events.py", line 642, in run_until_complete
return future.result()
File "C:\Python39\lib\site-packages\discord\abc.py", line 1065, in send
data = await state.http.send_message(channel.id, content, tts=tts, embed=embed,
File "C:\Python39\lib\site-packages\discord\http.py", line 192, in request
async with self.__session.request(method, url, **kwargs) as r:
File "C:\Python39\lib\site-packages\aiohttp\client.py", line 1117, in __aenter__
self._resp = await self._coro
File "C:\Python39\lib\site-packages\aiohttp\client.py", line 448, in _request
with timer:
File "C:\Python39\lib\site-packages\aiohttp\helpers.py", line 635, in __enter__
raise RuntimeError(
RuntimeError: Timeout context manager should be used inside a task
asyncio.run creates a new event loop. You need to use the existing event loop that the discord.Client uses. You can retrieve this with Client.loop, asyncio.get_running_loop, or asyncio.get_event_loop.
You should probably also use asyncio.run_coroutine_threadsafe.
If you're using the current latest development version of Tweepy on the master branch, set to be released as v4.0, which it seems like you are, then you can also look into using AsyncStream
How can I get the response for every iteration, like a live stream feed?
Here is the RestAPI main.py:
from fastapi import FastAPI
from fastapi import Request
from fastapi import WebSocket
import asyncio
app = FastAPI()
#app.get("/ws_res")
async def websoc(websocket: WebSocket):
await websocket.accept()
for i in range(100000):
i = "John"
await asyncio.sleep(0.01)
await websocket.send_json({"msg": i})
await websocket.close()
Now, I am trying to get the response from python code but I'm receiving an error that says Unsupported upgrade request.
Here is the output from API side :
INFO: Started server process [67680]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
WARNING: Unsupported upgrade request.
Here is the python code that I used to access the API (test.py):
import asyncio
import websockets
async def hello():
uri = "ws://127.0.0.1:8000/ws_res"
async with websockets.connect(uri) as websocket:
greeting = await websocket.recv()
print(f"< {greeting['msg']}")
asyncio.get_event_loop().run_until_complete(hello())
Traceback (most recent call last):
File "test.py", line 12, in <module>
asyncio.get_event_loop().run_until_complete(hello())
File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
return future.result()
File "test.py", line 7, in hello
async with websockets.connect(uri) as websocket:
File "/home/test/env/lib/python3.8/site-packages/websockets/client.py", line 517, in __aenter__
return await self
File "/home/test/env/lib/python3.8/site-packages/websockets/client.py", line 542, in __await_impl__
await protocol.handshake(
File "/home/test/env/lib/python3.8/site-packages/websockets/client.py", line 296, in handshake
raise InvalidStatusCode(status_code)
websockets.exceptions.InvalidStatusCode: server rejected WebSocket connection: HTTP 400
Fastapi websocket endpoints need to be defined using the websocket decorator, not the get decorator:
#app.websocket("/ws_res")
async def websoc(websocket: WebSocket):
await websocket.accept()
for i in range(100000):
i = "John"
await asyncio.sleep(0.01)
await websocket.send_json({"msg": i})
await websocket.close()
See the documentation for full details: https://fastapi.tiangolo.com/advanced/websockets/
I'm trying to create a simple WebSocket server using websockets module in Python.
My task is to create a WebSocket server that sends a message to all the clients that are listening to it. The problem is that everytime a client disconnects, websockets launches an exception (ConnectionClosedOK or ConnectionClosedError, depending of what happened) that I need to catch because I have to unregister the clients that have disconnected so that the WebSocket stops to send messages in the ether (and stopping the WebSocket server throwing these exceptions everytime that he tries to send a message to a closed client).
Here's the server's code:
async def foo_call():
await asyncio.sleep(3)
print('Hi!')
async def register(websocket):
users.add(websocket)
await notify_users()
async def unregister(websocket):
users.remove(websocket)
async def start(websocket, path):
await register(websocket)
try:
await foo_call()
except websockets.ConnectionClosedError:
await unregister(websocket)
# WebSocket clients that are listening this WebSocket server
users = set()
# Open WebSocket server
start_server = websockets.serve(start, "localhost", 8765)
# Run asyncio event loop
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
And here's the traceback:
Task exception was never retrieved
future: <Task finished coro=<WebSocketCommonProtocol.send() done, defined at /home/vlado/Projects/dahua/venv/lib/python3.6/site-packages/websockets/protocol.py:521> exception=ConnectionClosedError('code = 1006 (connection closed abnormally [internal]), no reason',)>
Traceback (most recent call last):
File "/home/vlado/Projects/dahua/venv/lib/python3.6/site-packages/websockets/protocol.py", line 827, in transfer_data
message = await self.read_message()
File "/home/vlado/Projects/dahua/venv/lib/python3.6/site-packages/websockets/protocol.py", line 895, in read_message
frame = await self.read_data_frame(max_size=self.max_size)
File "/home/vlado/Projects/dahua/venv/lib/python3.6/site-packages/websockets/protocol.py", line 971, in read_data_frame
frame = await self.read_frame(max_size)
File "/home/vlado/Projects/dahua/venv/lib/python3.6/site-packages/websockets/protocol.py", line 1051, in read_frame
extensions=self.extensions,
File "/home/vlado/Projects/dahua/venv/lib/python3.6/site-packages/websockets/framing.py", line 105, in read
data = await reader(2)
File "/usr/lib/python3.6/asyncio/streams.py", line 672, in readexactly
raise IncompleteReadError(incomplete, n)
asyncio.streams.IncompleteReadError: 0 bytes read on a total of 2 expected bytes
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/vlado/Projects/dahua/venv/lib/python3.6/site-packages/websockets/protocol.py", line 555, in send
await self.ensure_open()
File "/home/vlado/Projects/dahua/venv/lib/python3.6/site-packages/websockets/protocol.py", line 803, in ensure_open
raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedError: code = 1006 (connection closed abnormally [internal]), no reason
I don't really understand how can I catch those exceptions thrown by websockets module.
I am trying to make an API call from within my service and I am running into event loop issues. Can someone help me understand what I am doing wrong?
Basically I want to make a service that does some calculations based on data pulled from a different service.
I can call this code below from a cli, but not when I start up a web app (i.e.) hitting http://127.0.0.1:8080/add
loop = asyncio.get_event_loop()
data = loop.run_until_complete(run_fetch(loop, 'http://google.com'))
Sample code:
from aiohttp import web
import aiohttp
import asyncio
async def add(request):
loop = asyncio.get_event_loop()
data = loop.run_until_complete(run_fetch(loop, 'http://google.com'))
return web.json_response(data)
async def fetch(client, url):
async with client.get(url) as resp:
assert resp.status == 200
return await resp.text()
async def run_fetch(loop, url):
async with aiohttp.ClientSession(loop=loop) as client:
html = await fetch(client, url)
return html
app = web.Application()
app.router.add_get('/add', add)
web.run_app(app, host='127.0.0.1', port=8080)
Exception:
Error handling request
Traceback (most recent call last):
File ".../aiohttp/web_protocol.py", line 417, in start
resp = yield from self._request_handler(request)
File ".../aiohttp/web.py", line 289, in _handle
resp = yield from handler(request)
File ".../sample.py", line 11, in add data = loop.run_until_complete(run_fetch(loop, 'http://google.com'))
File ".../python3.6/asyncio/base_events.py", line 454, in run_until_complete
self.run_forever()
File ".../python3.6/asyncio/base_events.py", line 408, in run_forever
raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
The run_until_complete is the way to run some async code from the sync context. Under the hood it adds provided future to the given ioloop and calls run_forever then returns result or throws exception (resolved future).
Actually you need to await run_fetch(loop, 'http://google.com'), since the caller function is asynchronous.