Async progress_handler call #373
Replies: 1 comment 3 replies
-
This runs the risk of blocking the scp operation if the callback you pass in blocks to do any async operations. That's one of the reasons it is a callback -- it's not supposed to take any significant amount of time. Since you don't need the return value from the handler here, I think a better solution might be to have your callback schedule a new async task to do whatever you want to do using asyncio.create_task(), or asyncio.ensure_future() if you are running something earlier than Python 3.7. In other words: async def async_progress_handler(srcpath, dstpath, bytes_copied, total_bytes):
"""Do whatever async operations you need to do"""
def progress_handler(srcpath, dstpath, bytes_copied, total_bytes):
"""Schedule the async progress handler"""
asyncio.ensure_future(async_progress_handler(srcpath, dstpath, bytes_copied, total_bytes)) I could potentially make this automatic when a coroutine is passed in, as you have here. I would probably actually call the progress handler and see if it returns an awaitable or not, though, and if so then call ensure_future() on that. To avoid code duplication, I'm thinking a small helper function which does that could be created such as: def _call_handler(handler, *args):
"""Call a handler, creating a task if it returns an awaitable"""
if handler:
result = handler(*args)
if inspect.isawaitable(result):
asyncio.ensure_future(result) One caution about this is that the progress handlers may run in parallel if they block, though, since the transfer will continue before the progress handler returns. Depending on how the handler is written, this may make it look like the progress is jumping forward and back, so perhaps it's better to leave the decision to the caller about whether to create a task or not. |
Beta Was this translation helpful? Give feedback.
-
Dear @ronf ,
first, thanks for this very useful library! I am developing a new feature for Scrapli, where I am trying to figure out what is the best way to prevent timeouts on main SSH channel during SCP operation. File transfer can take a lot of time and it makes the ongoing Scrapli connection stale and closed by the device.
As scp is blocking the thread while doing the copy, I tried to use
progress_handler
callback to make a quick and non-interactive send of an empty command to the staling SSH connection. Problem is that I can't await on theprogress_handler
as asyncssh does not handle that function call in async way :PI patched scp.py as a POC:
This worked fine actually. Do you find this useful? Or a bad idea?
Regards,
Viktor
Beta Was this translation helpful? Give feedback.
All reactions