Tornado unexpected exception in Future <Future cancelled> after timeout - python-3.x

I have set up a dask cluster. I can access a web dashboard, but when I'm trying to connect to the scheduler:
from dask.distributed import Client
client = Client('192.168.0.10:8786')
I get the following error:
tornado.application - ERROR - Exception in Future <Future cancelled> after timeout
Traceback (most recent call last):
File "/home/user/venv/lib/python3.5/site-packages/tornado/gen.py", line 970, in error_callback
future.result()
File "/usr/lib/python3.5/asyncio/futures.py", line 285, in result
raise CancelledError
concurrent.futures._base.CancelledError
Also, when I'm trying to execute some tasks on the cluster, all tasks are computed correctly and the result is fetched but then the above error occurs at the end.
Do you have any ideas how to fix it? I think it's a client problem, but where. Thank you very much.

You are running sync function in async tornado
Try this one:
from dask.distributed import Client
from tornado.ioloop import IOLoop
async def f():
client = await Client(address='192.168.0.10:8786', asynchronous=True)
future = client.submit(DO SOMETHING HERE)
result = await future
await client.close()
return result
IOLoop().run_sync(f)

Related

Uvicorn & asyncio: how can OSErrors with asyncio-only stack trace be caught?

I have an API server that runs asynchronous functions using FastAPI & uvicorn on Windows. Every now and then the program throws a network error via asyncio that causes the API to become unresponsive, but can't be caught by my script. I'd like to be able to put a trycatch somewhere that will catch this type of error so I can shut down & restart the server, but the traceback for the error doesn't have any of my code in it.
The following is a simple example to illustrate the file structure; first the file app.py defines the API:
from fastapi import FastAPI
app = FastAPI()
#app.get("/check-status")
async def root():
return {"Alive": True}
the server parameters are defined in a config.json:
{
"host": "0.0.0.0",
"port": 80
}
then the server is launched programmatically from another script run_app.py, with a trycatch block that should catch any errors thrown during the execution, show it on the console, and restart:
import uvicorn
import json
from datetime import datetime
if __name__ == '__main__':
with open('path/to/config.json', 'r') as f:
config = uvicorn.Config(**json.load(f))
server = uvicorn.Server(config)
try:
server.run()
except Exception as e:
err_timestamp = datetime.now().ctime()
print(f'{err_timestamp}: Exception raised\n{e}\nRestarting...')
server.shutdown()
server.run()
However, the server still ends up crashing after the following error:
Task exception was never retrieved
future: <Task finished name='Task-33094' coro=<IocpProactor.accept.<locals>.accept_coro() done, defined at C:\Users\Administrateur\AppData\Local\Programs\Python\Python38\lib\asyncio\windows_events.py:563> exception=OSError(22, 'The specified network name is no longer available', None, 64, None)>
Traceback (most recent call last):
File "C:\Users\Administrateur\AppData\Local\Programs\Python\Python38\lib\asyncio\windows_events.py", line 566, in accept_coro
await future
File "C:\Users\Administrateur\AppData\Local\Programs\Python\Python38\lib\asyncio\windows_events.py", line 812, in _poll
value = callback(transferred, key, ov)
File "C:\Users\Administrateur\AppData\Local\Programs\Python\Python38\lib\asyncio\windows_events.py", line 555, in finish_accept
ov.getresult()
OSError: [WinError 64] The specified network name is no longer available
Accept failed on a socket
socket: <asyncio.TransportSocket fd=732, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('0.0.0.0', 80)>
Traceback (most recent call last):
File "C:\Users\Administrateur\AppData\Local\Programs\Python\Python38\lib\asyncio\proactor_events.py", line 818, in loop
conn, addr = f.result()
File "C:\Users\Administrateur\AppData\Local\Programs\Python\Python38\lib\asyncio\windows_events.py", line 566, in accept_coro
await future
File "C:\Users\Administrateur\AppData\Local\Programs\Python\Python38\lib\asyncio\windows_events.py", line 812, in _poll
value = callback(transferred, key, ov)
File "C:\Users\Administrateur\AppData\Local\Programs\Python\Python38\lib\asyncio\windows_events.py", line 555, in finish_accept
ov.getresult()
OSError: [WinError 64] The specified network name is no longer available
Clearly, the error happens purely within asyncio, and isn't actually thrown at any point in the execution of my code, so I haven't been able to replicate this error myself to test a solution. I know this type of WinError is usually down to network issues and isn't something that can actually be solved by the API, but I need to at least be able to deal with it when it occurs.
Environment; Python 3.8.10, Uvicorn version 0.17.4, FastAPI version 0.73.0, Windows 10

Read public channel texts using Telegram API

I would like to create a small script that will fetch Telegram texts from a public channel (I am not the channel's admin).
I've found another question asked here:
Read the messages of the public channels from Telegram
I've tried using Telethon as said in the answer, but it didn't work:
from telethon.tl.functions.contacts import ResolveUsernameRequest
import telethon
client = telethon.TelegramClient("session.txt", api_id=XYZ, api_hash='XYZ')
client.connect()
response = client.invoke(ResolveUsernameRequest("test"))
print(response.channel_id)
print(response.access_hash)
Throwing this error:
C:/Users/mypc/PycharmProjects/untitled/aa.py:5: RuntimeWarning: coroutine 'TelegramBaseClient.connect' was never awaited
client.connect()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Traceback (most recent call last):
File "C:/Users/mypc/PycharmProjects/untitled/aa.py", line 6, in <module>
response = client.invoke(ResolveUsernameRequest("test"))
AttributeError: 'TelegramClient' object has no attribute 'invoke'
I've tried reading the API documentation, but I didn't fully understand how those calls work:
https://core.telegram.org/method/channels.exportMessageLink
https://core.telegram.org/method/channels.joinChannel
https://core.telegram.org/method/channels.getMessages
I'd be grateful if someone could explain to me how those work.
That answer is very old. If we check Telethon's Quick-Start we have enough code to do what you need:
from telethon import TelegramClient
# Remember to use your own values from my.telegram.org!
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
client = TelegramClient('anon', api_id, api_hash)
async def main():
# You can print the message history of any chat:
async for message in client.iter_messages('USERNAME OF THE CHANNEL'):
print(message.sender.username, message.text)
with client:
client.loop.run_until_complete(main())
Well like it says, TelegramClient has no invoke method. Have you tried client(ResolveUsernameRequest("test"))?

Finding source of PyMySQL error - err.InterfaceError("(0, '')")

I am a Discord bot developer, and recently completed an order. The client upon setting the application up on their server initially had no issues, but according to them after running for "about three hours" the program begins spitting a specific stack trace error and no longer accepting commands.
The bot is built using Discord.py and uses Peewee as an ORM, using PyMySQL as the database driver. The server the client is running it on is hosted by DigitalOcean and if any information about the hardware, etc. is needed the client is able to give me that information on request. We have already attempted uninstalling and reinstalling all dependencies, as well as trying different distributions of them, but the errors persist.
This is the exact trace that the client is receiving:
File "/usr/local/lib/python3.6/dist-packages/peewee.py", line 2666, in __exit__
reraise(new_type, new_type(*exc_args), traceback)
File "/usr/local/lib/python3.6/dist-packages/peewee.py", line 179, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.6/dist-packages/peewee.py", line 2875, in execute_sql
cursor.execute(sql, params or ())
File "/usr/local/lib/python3.6/dist-packages/pymysql/cursors.py", line 170, in execute
result = self._query(query)
File "/usr/local/lib/python3.6/dist-packages/pymysql/cursors.py", line 328, in _query
conn.query(q)
File "/usr/local/lib/python3.6/dist-packages/pymysql/connections.py", line 516, in query
self._execute_command(COMMAND.COM_QUERY, sql)
File "/usr/local/lib/python3.6/dist-packages/pymysql/connections.py", line 750, in _execute_command
raise err.InterfaceError("(0, '')")
peewee.InterfaceError: (0, '')
The relevant portions from my database.py file, where the database connection is opened:
import discord
from peewee import *
from config import db_host, db_port, mysql_db_name, \
mysql_db_username, mysql_db_password
db_connection = MySQLDatabase(
mysql_db_name,
user = mysql_db_username,
password = mysql_db_password,
host = db_host,
port = db_port
)
def create_db_tables():
# create_tables() does safe creation by default, and will simply not create
# table if it already exists
db_connection.create_tables([User])
The relevant portions from my bot.py file, specifically the bot startup function that runs when the bot is first opened, and the lines that create and start the bot client:
client = discord.Client()
async def bot_startup():
# Check for config changes
if client.user.name != config.bot_username:
print("Username Updated To: {}".format(config.bot_username))
await client.edit_profile(username=config.bot_username)
# Start 'playing' message
await client.change_presence(
game=discord.Game( name=config.playing_message )
)
# Prepare database
database.create_db_tables()
print("Database Connected")
print("Connected Successfully")
# ...
#client.event
async def on_ready():
await bot_startup()
# ...
client.run(config.token)
According to the client, restarting the bot temporarily solves the problem and it runs fine for a few hours before the errors start up again. The bot no longer responds to any incoming commands once the errors start, and if enough errors are thrown, crashes completely.
What is typically the cause of this error, and what steps should be taken to fix whatever is causing it?
discord.py is asynchronous whilst PyMySQL is not - therefore it is blocking the discord.py runtime. Instead of PyMySQL use AIOMySQL which is non-blocking and might just solve your error.
The timing of when the error appears makes me think of a problem I also encountered when communicating to a database.
The problem could be that since the connection is opened when the bot starts up (or even when the program begins its execution) and is used sporadically, the database might close the connection, therefore any further execution will result in an error. To combat this, I create this decorator for all the methods of my Database Class
def ensures_connected(f):
def wrapper(*args):
args[0].connection.ping(reconnect=True, attempts=3, delay=2)
return f(*args)
return wrapper
to be placed above any method or function that has to communicate with the database.
The line args[0].connection.ping(reconnect=True, attempts=3, delay=2) means that we will call on self.connection (since it is the first argument passed to the method when called) the method ping, that allows to reconnect if the connection was dropped.
self.connection in my code is an object returned by the method call MySQLConnection.connect and should be equivalent to your obejct db_connection
This decorator should be placed above the method definition like the following example :
def ensures_connected(f):
def wrapper(*args):
args[0].connection.ping(reconnect=True, attempts=3, delay=2)
return f(*args)
return wrapper
class Database:
def __init__(self):
self.connection = mysql.connector.connect(
user=self.username, password=password, host=self.host, database=self.database)
# ...
#ensures_connected
def is_member_registered(self, guild: Guild, member: Member):
# ...
return
According to this comment you can use following code for reconnect automatically:
‍
from peewee import *
from playhouse.shortcuts import ReconnectMixin
class ReconnectMySQLDatabase(ReconnectMixin, MySQLDatabase):
pass
db = ReconnectMySQLDatabase(...)

Task exception with aiohttp async request

Im trying to accelerate multiple get requests to a web service using asyncio and aiohttp.
For that im fetching my data from a postgresql database using psycopg2 module .fetchmany() inside a function and constructing a dictionary of 100 records to send as lists of dictionary urls to an async function named batch() . batch by batch process.
The problem im facing in batch() function is that some requests are logging the message below although the script continues and dont fail but im not able to catch and log this exceptions to later reprocess them.
Task exception was never retrieved
future: <Task finished coro=<batch.<locals>.fetch() done, defined at C:/PythonProjects/bindings/batch_fetch.py:34> exception=ClientOSError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None)>
Traceback (most recent call last):
File "C:/PythonProjects/bindings/batch_fetch.py", line 36, in fetch
async with session.get(url) as resp:
File "C:\Miniconda3\lib\site-packages\aiohttp\client.py", line 1005, in __aenter__
self._resp = await self._coro
File "C:\Miniconda3\lib\site-packages\aiohttp\client.py", line 497, in _request
await resp.start(conn)
File "C:\Miniconda3\lib\site-packages\aiohttp\client_reqrep.py", line 844, in start
message, payload = await self._protocol.read() # type: ignore # noqa
File "C:\Miniconda3\lib\site-packages\aiohttp\streams.py", line 588, in read
await self._waiter
aiohttp.client_exceptions.ClientOSError: [WinError 10054] An existing connection was forcibly closed by the remote host
Task exception was never retrieved
future: <Task finished coro=<batch.<locals>.fetch() done, defined at C:/PythonProjects/bindings/batch_fetch.py:34> exception=ClientConnectorError(10060, "Connect call failed ('xx.xxx.xx.xxx', 80)")>
Traceback (most recent call last):
File "C:\Miniconda3\lib\site-packages\aiohttp\connector.py", line 924, in _wrap_create_connection
await self._loop.create_connection(*args, **kwargs))
File "C:\Miniconda3\lib\asyncio\base_events.py", line 778, in create_connection
raise exceptions[0]
File "C:\Miniconda3\lib\asyncio\base_events.py", line 765, in create_connection
yield from self.sock_connect(sock, address)
File "C:\Miniconda3\lib\asyncio\selector_events.py", line 450, in sock_connect
return (yield from fut)
File "C:\Miniconda3\lib\asyncio\selector_events.py", line 480, in _sock_connect_cb
raise OSError(err, 'Connect call failed %s' % (address,))
TimeoutError: [Errno 10060] Connect call failed ('xx.xxx.xx.xxx', 80)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:/PythonProjects/bindings/batch_fetch.py", line 36, in fetch
async with session.get(url) as resp:
File "C:\Miniconda3\lib\site-packages\aiohttp\client.py", line 1005, in __aenter__
self._resp = await self._coro
File "C:\Miniconda3\lib\site-packages\aiohttp\client.py", line 476, in _request
timeout=real_timeout
File "C:\Miniconda3\lib\site-packages\aiohttp\connector.py", line 522, in connect
proto = await self._create_connection(req, traces, timeout)
File "C:\Miniconda3\lib\site-packages\aiohttp\connector.py", line 854, in _create_connection
req, traces, timeout)
File "C:\Miniconda3\lib\site-packages\aiohttp\connector.py", line 992, in _create_direct_connection
raise last_exc
File "C:\Miniconda3\lib\site-packages\aiohttp\connector.py", line 974, in _create_direct_connection
req=req, client_error=client_error)
File "C:\Miniconda3\lib\site-packages\aiohttp\connector.py", line 931, in _wrap_create_connection
raise client_error(req.connection_key, exc) from exc
aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host cms-uat.cme.in.here.com:80 ssl:None [Connect call failed ('xx.xxx.xx.xxx', 80)]
Im just entering into asyncio world as you can depict from my code, so all the advises on the full code approach for this scenario are very welcomme.
Thank you
full code below.
import psycopg2.extras
import asyncio
import json
from aiohttp import ClientSession
from aiohttp import TCPConnector
base_url = 'http://url-example/{}'
def query_db():
urls = []
# connection to postgres table , fetch data.
conn = psycopg2.connect("dbname='pac' user='user' host='db'")
cursor = conn.cursor('psycopg2 request', cursor_factory=psycopg2.extras.NamedTupleCursor)
sql = "select gid, paid from table"
cursor.execute(sql)
while True:
rec = cursor.fetchmany(100)
for item in rec:
record = {"gid": item.gid, "url": base_url.format(item.paid)}
urls.append(record.get('url'))
if not rec:
break
# send batch for async batch request
batch(urls)
# empty list of urls for new async batch request
urls = []
def batch(urls):
async def fetch(url):
async with ClientSession() as session:
async with session.get(url) as resp:
if resp.status == 200:
response = await resp.json()
# parse the url to fetch the point address id.
paid = str(resp.request_info.url).split('/')[4].split('?')[0]
# build the dictionary with pa id and full response.
resp_dict = {'paid': paid, 'response': response}
with open('sucessful.json', 'a') as json_file:
json.dump(resp_dict, json_file)
json_file.write("\n")
elif resp.status is None:
print(resp.status)
elif resp.status != 200:
print(resp.status)
response = await resp.json()
# parse the url to fetch the paid.
paid = str(resp.request_info.url).split('/')[4].split('?')[0]
# build the dictionary with paid and full response.
resp_dict = {'paid': paid, 'response': response}
with open('failed.json', 'a') as json_file:
json.dump(resp_dict, json_file)
json_file.write("\n")
loop = asyncio.get_event_loop()
tasks = []
for url in urls:
task = asyncio.ensure_future(fetch(url))
tasks.append(task)
try:
loop.run_until_complete(asyncio.wait(tasks))
except Exception:
print("exception consumed")
if __name__ == "__main__":
query_db()
Task exception was never retrieved
You see this warning when you've created some task, it finished with exception, but you never explicitly retrieved (awaited) for its result. Here's related doc section.
I bet in your case problem is with the line
loop.run_until_complete(asyncio.wait(tasks))
asyncio.wait() by default just waits when all tasks are done. It doesn't distinguish tasks finished normally or with exception, it just blocks until everything finished. In this case it's you job to retrieve exceptions from finished tasks and following part won't help you with this since asyncio.wait() will never raise an error:
try:
loop.run_until_complete(asyncio.wait(tasks))
except Exception:
print('...') # You will probably NEVER see this message
If you want to catch error as soon as it happened in one of tasks I can advice you to use asyncio.gather(). By default it will raise first happened exception. Note however that it is you job to cancel pending tasks if you want their graceful shutdown.

With pyppeteer how to make a request with client cert?

I have the need to reach a page using client certificate with pyppeteer,
i have seen that its possible with puppeteer itself here,
but my attempts lead to an invalid state errror with python3. Im not sure whether my attempt is entirely correct, but it follows the spirit of the issue comment in puppeteer. I would expect it to be possible, hence my attempts, here is the error:
[E:pyppeteer.connection] connection unexpectedly closed
Task exception was never retrieved
future: <Task finished coro=<Connection._async_send() done, defined at /home/data/experim/jaenv/lib/python3.6/site-packages/pyppeteer/connection.py:69> exception=InvalidStateError('invalid state',)>
Traceback (most recent call last):
File "/home/data/experim/jaenv/lib/python3.6/site-packages/pyppeteer/connection.py", line 73, in _async_send
await self.connection.send(msg)
File "/home/data/experim/jaenv/lib/python3.6/site-packages/websockets/protocol.py", line 467, in send
yield from self.write_frame(True, OP_TEXT, data.encode('utf-8'))
File "/home/data/experim/jaenv/lib/python3.6/site-packages/websockets/protocol.py", line 919, in write_frame
yield from self.ensure_open()
File "/home/data/experim/jaenv/lib/python3.6/site-packages/websockets/protocol.py", line 646, in ensure_open
) from self.transfer_data_exc
websockets.exceptions.ConnectionClosed: WebSocket connection is closed: code = 1006 (connection closed abnormally [internal]), no reason
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/data/experim/jaenv/lib/python3.6/site-packages/pyppeteer/connection.py", line 79, in _async_send
await self.dispose()
File "/home/data/experim/jaenv/lib/python3.6/site-packages/pyppeteer/connection.py", line 170, in dispose
await self._on_close()
File "/home/data/experim/jaenv/lib/python3.6/site-packages/pyppeteer/connection.py", line 153, in _on_close
f'Protocol error {cb.method}: Target closed.', # type: ignore
asyncio.base_futures.InvalidStateError: invalid state
This is the attempt that leads to the above error:
import asyncio
from pyppeteer import launch
from pyppeteer.network_manager import Request
import requests
async def interceptor(interceptReq, cert,key):
res = requests.get(interceptReq.url , cert=('../../widshared/certexp.cer','../../widshared/certpriv.pem'))
if not res.ok:
return await interceptReq.abort('connectionrefused')
else:
return await interceptReq.respond({
'status': res.status_code,
'headers': res.headers,
'body': res.content
})
async def main():
browser = await launch(headless = True )
page = await browser.newPage()
await page.setRequestInterception(True)
with open("../../widshared/certexp.cer", 'r') as cr:
cert = cr.read()
with open("../../widshared/certpriv.pem", 'r') as cr:
key = cr.read()
page.on('request', lambda interceptReq: asyncio.ensure_future(interceptor(interceptReq, cert, key )) )
await page.goto('https://client.badssl.com')
await page.screenshot({'path': 'clientbadssl.png'})
await browser.close()
asyncio.get_event_loop().run_until_complete(main())

Resources