2017-07-17 6 views
0

したがって、Pythonを使用している間にローカルマシンにダウンロードせずにFTPサーバーから行数を読み取りカウントする必要があります。Pythonを使用している間にFTPファイルをローカルにダウンロードせずに行数をカウントするには

私は、サーバーに接続するためのコードを知っている:

ftp = ftplib.FTP('example.com') //Object ftp set as server address 
ftp.login ('username' , 'password') // Login info 
ftp.retrlines('LIST') // List file directories 
ftp.cwd ('/parent folder/another folder/file/') //Change file directory 

それはすでにローカルに保存されている/ダウンロードした場合、私はまた、ラインの数をカウントするための基本的なコードを知っている:

with open('file') as f: 
...  count = sum(1 for line in f) 
...  print (count)     

ローカルシステムにファイルをダウンロードすることなく、これらの2つのコードをどのように接続するかを知るだけでいいです。

何か助けていただければ幸いです。 ありがとう

+3

あなたは*ダウンロードする必要があります*とにかく*データ*は行を数えます。ディスクに保存するのを避けることができます。 –

答えて

1

私の知る限り、FTPはファイルコンテンツを実際にダウンロードせずに読み取る機能を提供していません。しかし、あなたがIs it possible to read FTP files without writing them using Python? のようなものを使用して試みることができる(あなたが使用しているPythonのものを指定していない)

#!/usr/bin/env python 
from ftplib import FTP 

def countLines(s): 
    print len(s.split('\n')) 

ftp = FTP('ftp.kernel.org') 
ftp.login() 
ftp.retrbinary('RETR /pub/README_ABOUT_BZ2_FILES', countLines) 

参照のみ

0

方法があり、このコードを取るしてください:私は、一枚の適応私はプロセスcsvファイルのために "オンザフライ"で作成したコードです。生産者 - 消費者問題のアプローチによる実装です。このパターンを適用すると、各タスクをスレッド(またはプロセス)に割り当て、巨大なリモートファイルの部分的な結果を表示することができます。 ftp要求に合わせて変更することができます。

ダウンロードストリームはキューに保存され、「オンザフライで」消費されます。 HDDの余分なスペースとメモリの効率が不要です。 Fedora Core 25 x86_64のPython 3.5.2(バニラ)でテストされています。

これは(HTTP経由)FTPに適合ソースが取得され:

from threading import Thread, Event 
from queue import Queue, Empty 
import urllib.request,sys,csv,io,os,time; 
import argparse 

FILE_URL = 'http://cdiac.ornl.gov/ftp/ndp030/CSV-FILES/nation.1751_2010.csv' 


def download_task(url,chunk_queue,event): 

    CHUNK = 1*1024 
    response = urllib.request.urlopen(url) 
    event.clear() 

    print('%% - Starting Download - %%') 
    print('%% - ------------------ - %%') 
    '''VT100 control codes.''' 
    CURSOR_UP_ONE = '\x1b[1A' 
    ERASE_LINE = '\x1b[2K' 
    while True: 
     chunk = response.read(CHUNK) 
     if not chunk: 
      print('%% - Download completed - %%') 
      event.set() 
      break 
     chunk_queue.put(chunk) 

def count_task(chunk_queue, event): 
    part = False 
    time.sleep(5) #give some time to producer 
    M=0 
    contador = 0 
    '''VT100 control codes.''' 
    CURSOR_UP_ONE = '\x1b[1A' 
    ERASE_LINE = '\x1b[2K' 
    while True: 
     try: 
      #Default behavior of queue allows getting elements from it and block if queue is Empty. 
      #In this case I set argument block=False. When queue.get() and queue Empty ocurrs not block and throws a 
      #queue.Empty exception that I use for show partial result of process. 
      chunk = chunk_queue.get(block=False) 
      for line in chunk.splitlines(True): 
       if line.endswith(b'\n'): 
        if part: ##for treat last line of chunk (normally is a part of line) 
         line = linepart + line 
         part = False 
        M += 1 
       else: 
       ##if line not contains '\n' is last line of chunk. 
       ##a part of line which is completed in next interation over next chunk 
        part = True 
        linepart = line 
     except Empty: 
      # QUEUE EMPTY 
      print(CURSOR_UP_ONE + ERASE_LINE + CURSOR_UP_ONE) 
      print(CURSOR_UP_ONE + ERASE_LINE + CURSOR_UP_ONE) 
      print('Downloading records ...') 
      if M>0: 
       print('Partial result: Lines: %d ' % M) #M-1 because M contains header 
      if (event.is_set()): #'THE END: no elements in queue and download finished (even is set)' 
       print(CURSOR_UP_ONE + ERASE_LINE+ CURSOR_UP_ONE) 
       print(CURSOR_UP_ONE + ERASE_LINE+ CURSOR_UP_ONE) 
       print(CURSOR_UP_ONE + ERASE_LINE+ CURSOR_UP_ONE) 
       print('The consumer has waited %s times' % str(contador)) 
       print('RECORDS = ', M) 
       break 
      contador += 1 
      time.sleep(1) #(give some time for loading more records) 

def main(): 


    chunk_queue = Queue() 
    event = Event() 
    args = parse_args() 
    url = args.url 

    p1 = Thread(target=download_task, args=(url,chunk_queue,event,)) 
    p1.start() 
    p2 = Thread(target=count_task, args=(chunk_queue,event,)) 
    p2.start() 
    p1.join() 
    p2.join() 

# The user of this module can customized one parameter: 
# + URL where the remote file can be found. 

def parse_args(): 
    parser = argparse.ArgumentParser() 
    parser.add_argument('-u', '--url', default=FILE_URL, 
         help='remote-csv-file URL') 
    return parser.parse_args() 


if __name__ == '__main__': 
    main() 

使用

$ python ftp-data.py -u <ftp-file> 

例のGithubに

python ftp-data-ol.py -u 'http://cdiac.ornl.gov/ftp/ndp030/CSV-FILES/nation.1751_2010.csv' 
The consumer has waited 0 times 
RECORDS = 16327 

CSVバージョン:https://github.com/AALVAREZG/csv-data-onthefly

+0

注:Windowsでこのスクリプトを実行すると、VT100コンソール制御コードはVT100互換端末でのみ動作します。 – alvarez

+0

これはPythonに関する私の知識の上にあります(私はまだ学んでいます)。私はこれをどのように使用できるかを理解する時間が必要です。あなたの助けをありがとう:) –

+0

マルチスレッドとキューのデータ構造のいくつかの基本的な知識と、コードは非常にシンプルです(私もPythonの学習の第一歩にあります);-)。 – alvarez

関連する問題