2

I am trying to use ftplib to count the number of lines in a file. This is what I have come up with so far.

ftp = FTP('ftp2.xxx.yyy')
ftp.login(user='xxx', passwd='yyy')
count = 0
def countLines(s):
    nonlocal count
    count += 1
    x=str(s).split('\\r')
    count += len(x)

ftp.retrbinary('RETR file_name'], countLines)

But the line count is off by a few ( I get about 20 more ), How can I fix it / Is there a better simpler solution

Dhanushka Amarakoon
  • 3,502
  • 5
  • 31
  • 43

2 Answers2

3

You have to use FTP.retrlines, not FTP.retrbinary.

count = 0
def countLines(s):
    global count
    count += 1

ftp.retrlines('RETR file_name', countLines)

For FTP.retrbinary:

The callback function is called for each block of data received

While for FTP.retrlines:

The callback function is called for each line with a string argument containing the line with the trailing CRLF stripped.


With FTP.retrbinary you get more, because if a block ends in a middle of a line, that line is counted twice.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
1

As suggested, use FTP.retrlines, but if you must use FTP.retrbinary, you will need to count on only each "\n", and not with each callback as well.

import ftplib

class FTPLineCounter(object):

    def __init__(self):
        self.count = 0

    def __call__(self, file_text):
        """Count the lines as the file is received"""
        self.count += file_text.count(b"\n")



ftp = ftplib.FTP("localhost")
ftp.login()

counter = FTPLineCounter()

ftp.retrbinary("RETR file_name", counter)

print(counter.count)
alxwrd
  • 2,320
  • 16
  • 28
  • You need something like `self.count += file_text.count("\n")` - Though you will still miss the last line, if it is not terminated with CRLF. – Martin Prikryl Sep 27 '17 at 12:31