admin管理员组文章数量:1291383
I'm writing a script that will transfer large amounts of data to an SFTP server, and I'd like to have some sort of terminal print-out during the long loading time for troubleshooting/debugging. I'm using paramiko for the SFTP connection and file writing.
What I currently have it this:
remote_zip_file = sftp_client.file(file_name_with_path, "wb")
remote_zip_file.write(my_data)
Is there any way to run a while
loop (or something similar) that runs while paramiko.sftp_file.SFTPFile
is being written?
What I'd like is something like this (pseudo code):
remote_zip_file = sftp_client.file(file_name_with_path, "wb")
while remote_zip_file.write(my_data) == IN_PROGRESS:
time.sleep(1)
print('Some print out that shows that the file writing is in progress')
This question is concerning the actual write
function, not the put
function. Answers to question How to see (log) file transfer progress using paramiko? mention the built-in callback function that can be used, but this callback parameter isn't present in the paramiko.sftp_file.SFTPFile
class specified in the original question (paramiko documentation source).
I'm writing a script that will transfer large amounts of data to an SFTP server, and I'd like to have some sort of terminal print-out during the long loading time for troubleshooting/debugging. I'm using paramiko for the SFTP connection and file writing.
What I currently have it this:
remote_zip_file = sftp_client.file(file_name_with_path, "wb")
remote_zip_file.write(my_data)
Is there any way to run a while
loop (or something similar) that runs while paramiko.sftp_file.SFTPFile
is being written?
What I'd like is something like this (pseudo code):
remote_zip_file = sftp_client.file(file_name_with_path, "wb")
while remote_zip_file.write(my_data) == IN_PROGRESS:
time.sleep(1)
print('Some print out that shows that the file writing is in progress')
This question is concerning the actual write
function, not the put
function. Answers to question How to see (log) file transfer progress using paramiko? mention the built-in callback function that can be used, but this callback parameter isn't present in the paramiko.sftp_file.SFTPFile
class specified in the original question (paramiko documentation source).
1 Answer
Reset to default 0Here is a suggestion: read and write data in chunks (blocks) instead of the whole content. That way, you can display progress in between blocks. In the following sample, I upload a file from a local host to a remote one.
import contextlib
import fabric
import tqdm
def main():
hostname = "ssh-sandbox"
config = fabric.Config()
if hostname not in config.base_ssh_config.get_hostnames():
raise SystemExit(f"{hostname} not found in ~/.ssh/config")
with contextlib.ExitStack() as stack:
conn = stack.enter_context(fabric.Connection(host=hostname))
sftp = stack.enter_context(conn.sftp())
inf = stack.enter_context(open("/tmp/big", "rb"))
outf = stack.enter_context(sftp.file("/tmp/big", "wb"))
pbar = stack.enter_context(tqdm.tqdm(total=inf.seek(0, 2)))
inf.seek(0, 0)
# Read & write in chunks
chunk_size = 10 * 1024 * 1024
while chunk := inf.read(chunk_size):
outf.write(chunk)
pbar.update(chunk_size)
if __name__ == "__main__":
main()
Notes
I use the
tqdm
library to provide a progress bar. If you don't want to use it, then replace thepbar.update()
call with aprint()
to show the progressI read/write in chunk of 10MB, you can adjust the chunk size for better performance on your system
The
inf.seek(0, 2)
will seek to the end of the file and return its position, which is the file's size. After seeking to the end, I calledinf.seek(0, 0)
to move the read pointer back to the beginning of the fileI am using the
contextlib.ExitStack()
to avoid deeply nestedwith
statement. Without it, the code will be deeply nested like this:with fabric.Connection(host=hostname) as conn: with con.sftp() as sftp: with open("/tmp/big", "rb") as inf: with sftp.file("/tmp/big", "wb") as outf: with tqdm.tqdm(total=inf.seek(0, 2))) as pbar: inf.seek(0, 0) # The rest of the code ...
Update
Per request, I have updated the code to use paramiko
instead of fabric
.
import contextlib
import pathlib
import paramiko
import tqdm
def main():
hostname = "ssh-sandbox"
config = paramiko.config.SSHConfig()
config_path = pathlib.Path("~/.ssh/config").expanduser()
config = paramiko.config.SSHConfig.from_path(config_path)
if hostname not in config.get_hostnames():
raise SystemExit(f"{hostname} not found in ~/.ssh/config")
cfg = config.lookup(hostname=hostname)
with contextlib.ExitStack() as stack:
conn = stack.enter_context(paramiko.SSHClient())
conn.load_system_host_keys()
conn.connect(cfg["hostname"], username=cfg["user"])
sftp = stack.enter_context(conn.open_sftp())
print(sftp)
inf = stack.enter_context(open("/tmp/big", "rb"))
outf = stack.enter_context(sftp.file("/tmp/big", "wb"))
pbar = stack.enter_context(tqdm.tqdm(total=inf.seek(0, 2)))
inf.seek(0, 0)
# Read & write in chunks
chunk_size = 10 * 1024 * 1024
while chunk := inf.read(chunk_size):
outf.write(chunk)
pbar.update(chunk_size)
if __name__ == "__main__":
main()
本文标签: pythonRun loop while writing to paramiko SFTP file is in progressStack Overflow
版权声明:本文标题:python - Run loop while writing to paramiko SFTP file is in progress - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741504968a2382267.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论