Progress Display for ftplib using Rich Library in Python
The ftplib is included in Python batteries, which can be used to implement the client side of the FTP protocol. It’s compact and easy to use, but missing a user-friendly progress display. For example, if you have a long-time connection to upload / download a large file to / from the FTP server, the terminal tells you nothing about the progress of the file transfer.
Don’t panic.
Luckily, we have Rich, a Python library, showing rich text (with color and style) to the terminal. Especially, it can display continuously updated information regarding the progress of long running tasks / file copies etc. That is perfect for the scenario of file transfer with FTP server.
The main challenge is that the Progress in rich.progress has to be called every time you need to update the UI and we have to, at the same time, synchronize the actual progress of FTP file transfer.
OK, show me the code.
First, make sure you have rich library installed.
Then, double check if you get these dependencies imported.
1 | import time |
The implementation is straightforward with the help from the callback in FTP.retrbinary(). The callback function is called for each block of data received. And that is when we take the chance to update and render the progress display.
Here is an example of downloading from FTP server.
1 | def download_from_ftp(file_path): |
If you go through the comments I wrote for the above function, then the below class should be fairly self-explanatory to you. The handle() is where we reflect the changes in each iteration, yes in callbacks.
One thing you should be aware of is that FTP uses two separate TCP connections: one to carry commands and the other to transfer data. So in the case of a long-time file transfer, you need to talk to the command channel once a while, to keep it connected. ‘NOOP’ command is designed for this, to prevent the client from being automatically disconnected (by server) for being idle.
1 | class ftp_progress: |
As a final note, it should be mentioned that be careful of passing by reference in Python. If you don’t close / keep FTP connections correctly with the server, strange things (not the TV show) cound happen.
And, stay away from the nested callbacks, always.
Ref:
ftplib — FTP protocol client
https://docs.python.org/3/library/ftplib.html
Rich’s documentation
https://rich.readthedocs.io/en/stable/index.html
Progress Display (Rich)
https://rich.readthedocs.io/en/stable/progress.html