2009-10-20 33 views
23

Sto provando a leggere un file da un server usando ssh da python. Sto usando paramiko per connetterti. Posso connettermi al server ed eseguire un comando come 'cat filename' e recuperare i dati dal server, ma alcuni file che sto cercando di leggere hanno circa 1 GB o più di dimensione.Leggere un file dal server con ssh usando python

Come posso leggere il file sul server riga per riga usando python?

Ulteriori informazioni: ciò che viene fatto regolarmente è eseguire un comando "nomefile cat" e memorizzare il risultato in una variabile e risolverlo. Ma dal momento che il file qui è abbastanza grande, sto cercando un modo per leggere un file riga per riga dal server.

MODIFICA: Sono in grado di leggere una serie di dati e dividerli in righe ma il problema è che i dati ricevuti nel buffer non sempre includono le righe complete. per esempio, se il buffer ha 300 linee, l'ultima riga può essere solo metà della linea sul server e la prossima metà verrà recuperata nella successiva chiamata al server. Voglio le linee complete

EDIT 2: quale comando è possibile utilizzare per stampare linee in un file in un determinato intervallo. Come stampare le prime 100 righe, poi le successive 100 e così via? In questo modo il buffer conterrà sempre linee complete.

+2

si fa a non SFTP il file? –

+0

Quindi stai leggendo line-by-line perché non vuoi mettere i dati in una variabile di script della shell? Su quale fine viene impostata la variabile? La fine locale? È importante elaborare una riga sul lato vicino prima di leggere il prossimo sul fondo? –

risposta

44

Paramiko'sSFTPClient classe consente di ottenere un oggetto simile a file per leggere i dati da un file remoto in modo Pythonic.

Supponendo di avere un dialogo aperto SSHClient:

+5

+1, MOLTO meglio che scherzare con il gatto (per quanto mi piaccia felini! -). –

+0

Nel mio caso, il contenuto del file è un dato json in una singola riga (che voglio fare json.load e archiviare in una variabile). La dimensione di questo file è ~ 200 MB. Quando provo a leggere la riga in remote_file, non ritorna mai, è solo bloccato. Qualcuno può aiutarmi con questo? –

4

Cosa intendete per "linea per linea" - ci sono molti buffer di dati tra gli host di rete e nessuno di essi è orientato alla linea.

Così puoi leggere un mucchio di dati, quindi dividerli in linee all'estremità vicina.

ssh otherhost cat somefile | python process_standard_input.py | do_process_locally 

Oppure si può avere un processo di lettura una serie di dati in fondo, disgregare e formattare riga per riga e inviarlo a voi.

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

L'unica differenza che mi interessa è il modo in cui riduce il volume dei dati su un tubo di rete limitato. Nella tua situazione potrebbe, o potrebbe non avere importanza.

Non c'è niente di sbagliato in generale con l'utilizzo di cat su una pipe SSH per spostare gigabyte di dati.

3
#!/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) 
+0

Un buon esempio di paramiko, ma evidenzia ancora la natura non orientata alla linea di questo tipo di attività. –

+0

Continua a leggerlo fino a quando non ottieni una nuova riga o un altro carattere che termina la linea. – g33kz0r

9

Ecco una proroga per @Matt Good's answer:

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) 
+0

Non ho mai visto contextlib.closing prima. Quindi questo ti permette di trasformare qualsiasi cosa con un metodo close() in una cosa simile a Context Manager, nonostante possa non avere \ _ \ _ inserire \ _ \ _ e \ _ \ _ uscire \ _ \ _? – hughdbrown

+0

@hughbrown: Sì. Qualunque oggetto con il metodo '.close()' funzionerà. L'implementazione di 'closing' è banale, si veda http://svn.python.org/view/python/trunk/Lib/contextlib.py?view=markup – jfs

+0

In effetti' con sftp.open ('remote_filename') come f : 'funzionerebbe anche con – taras

Problemi correlati