Расширение ответа NERV - что очень помогло мне, вот как я смог решить свою проблему с неявным подключением TLS на порту 990, требующим аутентификации.
Имя файла: ImplicitTLS.py
from ftplib import FTP_TLS
import socket
import ssl
class tyFTP(FTP_TLS):
def __init__(self, host='', user='', passwd='', acct='', keyfile=None, certfile=None, timeout=60):
FTP_TLS.__init__(self, host, user, passwd, acct, keyfile, certfile, timeout)
def connect(self, host='', port=0, timeout=-999):
if host != '':
self.host = host
if port > 0:
self.port = port
if timeout != -999:
self.timeout = timeout
try:
self.sock = socket.create_connection((self.host, self.port), self.timeout)
self.af = self.sock.family
self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile, ssl_version=ssl.PROTOCOL_TLSv1)
self.file = self.sock.makefile('rb')
self.welcome = self.getresp()
except Exception as e:
print e
return self.welcome
Затем из моего основного приложения я сделал это:
from ImplicityTLS import tyFTP
server = tyFTP()
server.connect(host="xxxxx", port=990)
server.login(user="yyyy", passwd="fffff")
server.prot_p()
И это все, я смог загружать файлы и т. д. Репозиты отправляются в NERV для получения исходного ответа.
Вы не можете получить ничего лучше.
В конце концов, любое решение должно будет прочитать весь файл, выяснить, сколько \n
у вас есть, и вернуть этот результат.
У вас есть лучший способ сделать это, не читая весь файл? Не уверен ... Лучшее решение всегда будет связано с I / O-привязкой, лучше всего это сделать, чтобы убедиться, что вы не используете ненужную память, но похоже, что у вас есть это.
print open('file.txt', 'r').read().count("\n") + 1
результатом открытия файла является итератор, который может быть преобразован в последовательность, которая имеет длину:
with open(filename) as f:
return len(list(f))
, это более кратким, чем ваш явный цикл, и позволяет избежать enumerate
.
Чтобы завершить описанные выше методы, я попробовал вариант с файловым модулем:
import fileinput as fi
def filecount(fname):
for line in fi.input(fname):
pass
return fi.lineno()
И передал файл строк длиной 60 мил всем указанным выше методам:
mapcount : 6.1331050396
simplecount : 4.588793993
opcount : 4.42918205261
filecount : 43.2780818939
bufcount : 0.170812129974
Для меня немного неожиданно, что fileinput - это то, что плохо и масштабируется намного хуже, чем все другие методы ...
Однострочное решение bash, подобное , этот ответ , используя современную функцию subprocess.check_output
:
def line_count(file):
return int(subprocess.check_output('wc -l {}'.format(file), shell=True).split()[0])
wc -l
занимает ~ 5 секунд.
– Shan Dou
27 June 2018 в 16:06
Я бы использовал метод файлового объекта Python readlines
, как показано ниже:
with open(input_file) as foo:
lines = len(foo.readlines())
Это открывает файл, создает список строк в файле, подсчитывает длину списка, сохраняет это к переменной и снова закрывает файл.
xreadlines
устарел с 2,3, так как он просто возвращает итератор. for line in file
является заявленной заменой. См .: docs.python.org/2/library/stdtypes.html#file.xreadlines
– Kumba
5 August 2018 в 22:53
Я изменил буферный случай следующим образом:
def CountLines(filename):
f = open(filename)
try:
lines = 1
buf_size = 1024 * 1024
read_f = f.read # loop optimization
buf = read_f(buf_size)
# Empty file
if not buf:
return 0
while buf:
lines += buf.count('\n')
buf = read_f(buf_size)
return lines
finally:
f.close()
Теперь также пустые файлы и последняя строка (без\n) подсчитываются.
Почему бы не прочитать первые 100 и последние 100 строк и оценить среднюю длину линии, а затем разделить общий размер файла на эти числа? Если вам не нужно точное значение, это может сработать.
def count_text_file_lines(path):
with open(path, 'rt') as file:
line_count = sum(1 for _line in file)
return line_count
Почему бы не работать следующее?
import sys
# input comes from STDIN
file = sys.stdin
data = file.readlines()
# get total number of lines in file
lines = len(data)
print lines
В этом случае функция len использует входные строки как средство определения длины.
Одна строка, возможно довольно быстро:
num_lines = sum(1 for line in open('myfile.txt'))
Как насчет этого?
import fileinput
import sys
counter=0
for line in fileinput.input([sys.argv[1]]):
counter+=1
fileinput.close()
print counter
Если вы хотите получить количество строк в Python в Linux, я рекомендую этот метод:
import os
print os.popen("wc -l file_path").readline().split()[0]
file_path может быть как абстрактным, так и относительным путем. Надеюсь, это поможет.
def line_count(path):
count = 0
with open(path) as lines:
for count, l in enumerate(lines, start=1):
pass
return count
Здесь представлена программа python для использования библиотеки многопроцессорности для распределения подсчета строк по машинам / ядрам. Мой тест улучшает подсчет 20-миллионного файла линии с 26 секунд до 7 секунд, используя 8-ядерный сервер Windows 64. Примечание: не использование карт памяти делает вещи намного медленнее.
import multiprocessing, sys, time, os, mmap
import logging, logging.handlers
def init_logger(pid):
console_format = 'P{0} %(levelname)s %(message)s'.format(pid)
logger = logging.getLogger() # New logger at root level
logger.setLevel( logging.INFO )
logger.handlers.append( logging.StreamHandler() )
logger.handlers[0].setFormatter( logging.Formatter( console_format, '%d/%m/%y %H:%M:%S' ) )
def getFileLineCount( queues, pid, processes, file1 ):
init_logger(pid)
logging.info( 'start' )
physical_file = open(file1, "r")
# mmap.mmap(fileno, length[, tagname[, access[, offset]]]
m1 = mmap.mmap( physical_file.fileno(), 0, access=mmap.ACCESS_READ )
#work out file size to divide up line counting
fSize = os.stat(file1).st_size
chunk = (fSize / processes) + 1
lines = 0
#get where I start and stop
_seedStart = chunk * (pid)
_seekEnd = chunk * (pid+1)
seekStart = int(_seedStart)
seekEnd = int(_seekEnd)
if seekEnd < int(_seekEnd + 1):
seekEnd += 1
if _seedStart < int(seekStart + 1):
seekStart += 1
if seekEnd > fSize:
seekEnd = fSize
#find where to start
if pid > 0:
m1.seek( seekStart )
#read next line
l1 = m1.readline() # need to use readline with memory mapped files
seekStart = m1.tell()
#tell previous rank my seek start to make their seek end
if pid > 0:
queues[pid-1].put( seekStart )
if pid < processes-1:
seekEnd = queues[pid].get()
m1.seek( seekStart )
l1 = m1.readline()
while len(l1) > 0:
lines += 1
l1 = m1.readline()
if m1.tell() > seekEnd or len(l1) == 0:
break
logging.info( 'done' )
# add up the results
if pid == 0:
for p in range(1,processes):
lines += queues[0].get()
queues[0].put(lines) # the total lines counted
else:
queues[0].put(lines)
m1.close()
physical_file.close()
if __name__ == '__main__':
init_logger( 'main' )
if len(sys.argv) > 1:
file_name = sys.argv[1]
else:
logging.fatal( 'parameters required: file-name [processes]' )
exit()
t = time.time()
processes = multiprocessing.cpu_count()
if len(sys.argv) > 2:
processes = int(sys.argv[2])
queues=[] # a queue for each process
for pid in range(processes):
queues.append( multiprocessing.Queue() )
jobs=[]
prev_pipe = 0
for pid in range(processes):
p = multiprocessing.Process( target = getFileLineCount, args=(queues, pid, processes, file_name,) )
p.start()
jobs.append(p)
jobs[0].join() #wait for counting to finish
lines = queues[0].get()
logging.info( 'finished {} Lines:{}'.format( time.time() - t, lines ) )
Вы можете выполнить подпроцесс и запустить wc -l filename
import subprocess
def file_len(fname):
p = subprocess.Popen(['wc', '-l', fname], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result, err = p.communicate()
if p.returncode != 0:
raise IOError(err)
return int(result.strip().split()[0])
Как насчет этого
def file_len(fname):
counts = itertools.count()
with open(fname) as f:
for _ in f: counts.next()
return counts.next()
Как об этом однострочном лайнере:
file_length = len(open('myfile.txt','r').read().split('\n'))
Получает 0,003 секунды, используя этот метод, чтобы время его в файле 3900 строк
def c():
import time
s = time.time()
file_length = len(open('myfile.txt','r').read().split('\n'))
print time.time() - s
def file_len(full_path):
""" Count number of lines in a file."""
f = open(full_path)
nr_of_lines = sum(1 for line in f)
f.close()
return nr_of_lines
enumerate()
- это начальный счет в соответствии с docs.python.org/2/library/functions.html#enumerate
– MarkHu
24 July 2017 в 22:59
Мне пришлось опубликовать это по аналогичному вопросу, пока мой рейтинг репутации не подскочил (спасибо тому, кто наткнулся на меня!).
Все эти решения игнорируют один из способов сделать этот запуск значительно быстрее, а именно, используя небуферизованный (необработанный) интерфейс, используя bytearrays и делая собственную буферизацию. (Это применимо только к Python 3. В Python 2 необработанный интерфейс может использоваться или не использоваться по умолчанию, но в Python 3 вы по умолчанию в Unicode.)
Использование модифицированной версии Я считаю, что следующий код быстрее (и немного больше pythonic), чем любое из предлагаемых решений:
def rawcount(filename):
f = open(filename, 'rb')
lines = 0
buf_size = 1024 * 1024
read_f = f.raw.read
buf = read_f(buf_size)
while buf:
lines += buf.count(b'\n')
buf = read_f(buf_size)
return lines
Используя отдельную функцию генератора, это быстрее запускает smidge:
def _make_gen(reader):
b = reader(1024 * 1024)
while b:
yield b
b = reader(1024*1024)
def rawgencount(filename):
f = open(filename, 'rb')
f_gen = _make_gen(f.raw.read)
return sum( buf.count(b'\n') for buf in f_gen )
Это можно сделать полностью с выражениями генераторов in-line, использующими itertools, но это выглядит довольно странно:
from itertools import (takewhile,repeat)
def rawincount(filename):
f = open(filename, 'rb')
bufgen = takewhile(lambda x: x, (f.raw.read(1024*1024) for _ in repeat(None)))
return sum( buf.count(b'\n') for buf in bufgen )
Вот мои тайминги:
function average, s min, s ratio
rawincount 0.0043 0.0041 1.00
rawgencount 0.0044 0.0042 1.01
rawcount 0.0048 0.0045 1.09
bufcount 0.008 0.0068 1.64
wccount 0.01 0.0097 2.35
itercount 0.014 0.014 3.41
opcount 0.02 0.02 4.83
kylecount 0.021 0.021 5.05
simplecount 0.022 0.022 5.25
mapcount 0.037 0.031 7.46
wccount
в этой таблице для инструмента оболочки подпроцесса wc
?
– Anentropic
11 November 2015 в 19:05
return sum(map(methodcaller("count", b'\n'), f_gen))
, импортировав methodcaller
из operator
, помогая ускорить это до любого (imap
из itertools
, а если python2)? Я бы также сконфигурировал математику 1024 * 1024 в _make_gen
, чтобы сохранить несколько дополнительных циклов. Хотелось бы увидеть сравнение с примером чистого генератора.
– Kumba
5 August 2018 в 22:57
Вот что я использую, кажется довольно чистым:
import subprocess
def count_file_lines(file_path):
"""
Counts the number of lines in a file using wc utility.
:param file_path: path to file
:return: int, no of lines
"""
num = subprocess.check_output(['wc', '-l', file_path])
num = num.split(' ')
return int(num[0])
UPDATE: это немного быстрее, чем использование чистого python, но за счет использования памяти. Подпроцесс разветвит новый процесс с тем же объемом памяти, что и родительский процесс, когда он выполнит вашу команду.
Я считаю, что файл с отображением памяти будет самым быстрым решением. Я попробовал четыре функции: функцию, отправленную OP (opcount
); простая итерация по строкам в файле (simplecount
); readline с картографированной памятью (mmap) (mapcount
); и решение для считывания буфера, предложенное Николаем Харечко (bufcount
).
Я выполнял каждую функцию пять раз и вычислял среднее время выполнения для текстового файла с 1,2 млн. строк.
Windows XP, Python 2.5, 2 ГБ оперативной памяти, процессор AMD 2 ГГц
Вот мои результаты:
mapcount : 0.465599966049
simplecount : 0.756399965286
bufcount : 0.546800041199
opcount : 0.718600034714
Изменить: номера для Python 2.6:
mapcount : 0.471799945831
simplecount : 0.634400033951
bufcount : 0.468800067902
opcount : 0.602999973297
Таким образом, стратегия чтения буфера, по-видимому, является самой быстрой для Windows / Python 2.6
Вот код:
from __future__ import with_statement
import time
import mmap
import random
from collections import defaultdict
def mapcount(filename):
f = open(filename, "r+")
buf = mmap.mmap(f.fileno(), 0)
lines = 0
readline = buf.readline
while readline():
lines += 1
return lines
def simplecount(filename):
lines = 0
for line in open(filename):
lines += 1
return lines
def bufcount(filename):
f = open(filename)
lines = 0
buf_size = 1024 * 1024
read_f = f.read # loop optimization
buf = read_f(buf_size)
while buf:
lines += buf.count('\n')
buf = read_f(buf_size)
return lines
def opcount(fname):
with open(fname) as f:
for i, l in enumerate(f):
pass
return i + 1
counts = defaultdict(list)
for i in range(5):
for func in [mapcount, simplecount, bufcount, opcount]:
start_time = time.time()
assert func("big_file.txt") == 1209138
counts[func].append(time.time() - start_time)
for key, vals in counts.items():
print key.__name__, ":", sum(vals) / float(len(vals))
wccount()
является самым быстрым gist.github.com/0ac760859e614cd03652
– jfs
31 January 2011 в 09:18
Я получил небольшое (4-8%) улучшение с этой версией, которая повторно использует постоянный буфер, поэтому он должен избегать любой из памяти или накладных расходов GC:
lines = 0
buffer = bytearray(2048)
with open(filename) as f:
while f.readinto(buffer) > 0:
lines += buffer.count('\n')
Вы можете играть с помощью размер буфера и, возможно, немного улучшится.
Что касается меня, этот вариант будет самым быстрым:
#!/usr/bin/env python
def main():
f = open('filename')
lines = 0
buf_size = 1024 * 1024
read_f = f.read # loop optimization
buf = read_f(buf_size)
while buf:
lines += buf.count('\n')
buf = read_f(buf_size)
print lines
if __name__ == '__main__':
main()
причинам: буферизация выполняется быстрее, чем чтение по строкам, а string.count
также очень быстро
Этот код короче и понятнее. Вероятно, это лучший способ:
num_lines = open('yourfile.ext').read().count('\n')
однострочное решение
import os
os.system("wc -l filename")
мой фрагмент
os.system ('wc -l * .txt')
blockquote> blockquote> blockquote>0 bar.txt 1000 command.txt 3 test_file.txt 1003 total
Другая возможность:
import subprocess
def num_lines_in_file(fpath):
return int(subprocess.check_output('wc -l %s' % fpath, shell=True).strip().split()[0])
Это самая быстрая вещь, которую я нашел, используя чистый python. Вы можете использовать любой объем памяти, который вы хотите, установив буфер, хотя 2 ** 16 кажется приятным пятном на моем компьютере.
from functools import partial
buffer=2**16
with open(myfile) as f:
print sum(x.count('\n') for x in iter(partial(f.read,buffer), ''))
Я нашел ответ здесь Почему строки чтения из stdin намного медленнее в C ++, чем Python? и немного изменили его. Его очень хорошо читать, чтобы понять, как быстро считать строки, хотя wc -l
все еще примерно на 75% быстрее, чем что-либо еще.
posix_fadvise()
может использоваться stackoverflow.com/questions/860893/… Хотя я не заметил никаких улучшений gist.github.com/0ac760859e614cd03652 – jfs 31 January 2011 в 10:08