web-dev-qa-db-fra.com

Lire un fichier du serveur avec SSH en utilisant Python

J'essaie de lire un fichier à partir d'un serveur en utilisant SSH de Python. J'utilise Paramiko pour me connecter. Je peux me connecter au serveur et exécuter une commande comme cat filename et récupérer les données du serveur, mais certains fichiers que j'essaie de lire mesurent environ 1 Go ou plus.

Comment puis-je lire le fichier ligne par ligne sur le serveur en utilisant Python?

Informations supplémentaires: ce qui est fait régulièrement est d'exécuter un cat filename commande et stocke le résultat dans une variable et travaille dessus. Mais comme le fichier ici est assez volumineux, je cherche un moyen de lire un fichier ligne par ligne sur le serveur.

EDIT: Je peux lire un tas de données et les diviser en lignes, mais le problème est que les données reçues dans le tampon n'incluent pas toujours les lignes complètes. Par exemple, si le tampon a 300 lignes, la dernière ligne peut ne représenter que la moitié de la ligne sur le serveur et la moitié suivante sera récupérée lors du prochain appel au serveur. Je veux des lignes complètes

EDIT 2: quelle commande puis-je utiliser pour imprimer des lignes dans un fichier dans une certaine plage. Comme imprimer les 100 premières lignes, puis les 100 suivantes et ainsi de suite? De cette façon, le tampon contiendra toujours des lignes complètes.

31
randomThought

la classe SFTPClient de Paramiko vous permet d'obtenir un objet de type fichier pour lire les données d'un fichier distant de manière Pythonique.

En supposant que vous avez un SSHClient ouvert:

sftp_client = ssh_client.open_sftp()
remote_file = sftp_client.open('remote_filename')
try:
    for line in remote_file:
        # process line
finally:
    remote_file.close()
56
Matt Good

Voici une extension de @ la réponse de Matt Good :

from contextlib     import closing
from fabric.network import connect

with closing(connect(user, Host, port)) as ssh, \
     closing(ssh.open_sftp()) as sftp, \
     closing(sftp.open('remote_filename')) as file:
    for line in file:
        process(line)
10
jfs
#!/usr/bin/env python
import paramiko
import select
client = paramiko.SSHClient()
client.load_system_Host_keys()
client.connect('yourhost.com')
transport = client.get_transport()
channel = transport.open_session()
channel.exec_command("cat /path/to/your/file")
while True:
  rl, wl, xl = select.select([channel],[],[],0.0)
  if len(rl) > 0:
      # Must be stdout
      print channel.recv(1024)
5
g33kz0r

Qu'entendez-vous par "ligne par ligne" - il y a beaucoup de tampons de données entre les hôtes du réseau, et aucun d'entre eux n'est orienté ligne.

Vous pouvez donc lire un tas de données, puis les diviser en lignes à l'extrémité proche.

ssh otherhost cat somefile | python process_standard_input.py | do_process_locally

Ou vous pouvez demander à un processus de lire un tas de données à l'extrémité distante, de les décomposer, de les formater ligne par ligne et de vous les envoyer.

scp process_standard_input.py otherhost
ssh otherhost python process_standard_input.py somefile |  do_process_locally

La seule différence dont je me soucierais est de savoir comment réduire le volume de données sur un canal réseau limité. Dans votre situation, cela peut ou non avoir de l'importance.

Il n'y a rien de mal en général à utiliser cat sur un canal SSH pour déplacer des gigaoctets de données.

4
Joe Koberg