MSTest является по существу NUnit, немного переделанный, с несколькими новыми возможностями (такими как установка блока и разрушение, не только приспособление и тестовый уровень), и пропускающий некоторые лучшие биты (такие как новые 2,4 ограничительных синтаксиса). NUnit более зрел, и существует больше поддержки его от других поставщиков; и конечно так как это всегда было свободно (тогда как MSTest только превратил его в Профессиональную версию 2008, прежде который это были способом более дорогие наименования), большинство проектов ALT.NET использует его.
Однако существуют некоторые компании, которые невероятно отказываются использовать что-то, что не сделало, чтобы Microsoft маркировала на нем, и особенно так код OSS. Так наличие официальной среды тестирования MS может быть мотивацией, что те компании должны получить тестирование; и давайте будем честны, это - тестирование, которое имеет значение, не, какой инструмент Вы используете (и использование код Tuomas Hietanen выше, можно почти сделать среду тестирования взаимозаменяемой).
Аналогичный вопрос здесь . Вы не можете смешивать итерацию и строку чтения, поэтому вам нужно использовать один или другой.
while True:
line1 = f.readline()
line2 = f.readline()
if not line2: break # EOF
...
, используйте next ()
, например
with open("file") as f:
for line in f:
print(line)
nextline = next(f)
print("next line", nextline)
....
Я бы поступил так же, как ghostdog74 , только с внешней попыткой и несколькими модификациями:
try:
with open(filename) as f:
for line1 in f:
line2 = f.next()
# process line1 and line2 here
except StopIteration:
print "(End)" # do whatever you need to do with line1 alone
Это делает код простым и в то же время надежным. Использование с
закрывает файл, если что-то еще происходит, или просто закрывает ресурсы после его исчерпания и выхода из цикла.
Обратите внимание, что с
требует 2,6 или 2,5 с включена функция with_statement
.
import itertools
with open('a') as f:
for line1,line2 in itertools.zip_longest(*[f]*2):
print(line1,line2)
itertools.zip_longest ()
возвращает итератор, поэтому он будет хорошо работать, даже если файл состоит из миллиардов строк.
Если количество строк нечетное, тогда для line2
установлено значение None
на последней итерации.
На Python2 вам нужно вместо этого использовать izip_longest
.
В комментариях он имеет Был задан вопрос, читает ли это решение сначала весь файл, а затем выполняет итерацию по файлу во второй раз.
Я считаю, что это не так. Строка с open ('a') as f
открывает дескриптор файла, но не читает файл. f
- итератор, поэтому его содержимое не читается, пока не будет запрошено. zip_longest
принимает итераторы в качестве аргументов и возвращает итератор.
zip_longest
действительно получает один и тот же итератор f дважды. Но в конечном итоге происходит то, что next (f)
вызывается для первого аргумента, а затем для второго аргумента. Поскольку next ()
вызывается на одном и том же базовом итераторе, выводятся последовательные строки. Это сильно отличается от чтения всего файла. На самом деле цель использования итераторов состоит именно в том, чтобы избежать чтения всего файла.
Поэтому я считаю, что решение работает должным образом - файл читается только один раз циклом for.
Чтобы подтвердить это, я запустил решение zip_longest вместо решения, использующего f.readlines ()
. Я помещаю input ()
в конец, чтобы приостановить скрипты, и запускал ps axuw
для каждого:
% ps axuw | grep zip_longest_method.py
unutbu 11119 2.2 0.2
4520 2712 pts / 0 S + 21:14 0:00 python /home/unutbu/pybin/zip_longest_method.py bigfile
% ps axuw | grep readlines_method.py
unutbu 11317 6,5 8,8
93908 91680 pts / 0 S + 21:16 0:00 python / home / unutbu /pybin/readlines_method.py bigfile
Строки чтения
явно читаются сразу во всем файле. Поскольку zip_longest_method
использует гораздо меньше памяти, я думаю, можно с уверенностью заключить, что он не читает весь файл сразу.
input ()
в конец, чтобы приостановить скрипты, и запускал ps axuw
для каждого:
% ps axuw | grep zip_longest_method.py
unutbu 11119 2.2 0.2
4520 2712 pts / 0 S + 21:14 0:00 python /home/unutbu/pybin/zip_longest_method.py bigfile
% ps axuw | grep readlines_method.py
unutbu 11317 6,5 8,8
93908 91680 pts / 0 S + 21:16 0:00 python / home / unutbu /pybin/readlines_method.py bigfile
Строки чтения
явно читаются сразу во всем файле. Поскольку zip_longest_method
использует гораздо меньше памяти, я думаю, можно с уверенностью заключить, что он не читает весь файл сразу.
input ()
в конец, чтобы приостановить скрипты, и запускал ps axuw
для каждого:
% ps axuw | grep zip_longest_method.py
unutbu 11119 2.2 0.2
4520 2712 pts / 0 S + 21:14 0:00 python /home/unutbu/pybin/zip_longest_method.py bigfile
% ps axuw | grep readlines_method.py
unutbu 11317 6,5 8,8
93908 91680 pts / 0 S + 21:16 0:00 python / home / unutbu /pybin/readlines_method.py bigfile
Строки чтения
явно читаются сразу во всем файле. Поскольку zip_longest_method
использует гораздо меньше памяти, я думаю, можно с уверенностью заключить, что он не читает весь файл сразу.
Строка чтения
явно читается сразу во всем файле. Поскольку zip_longest_method
использует гораздо меньше памяти, я думаю, можно с уверенностью заключить, что он не читает весь файл сразу.
Строка чтения
явно читается сразу во всем файле. Поскольку zip_longest_method
использует гораздо меньше памяти, я думаю, можно с уверенностью заключить, что он не читает весь файл сразу.
file_name = 'your_file_name' file_open = open(file_name, 'r') def handler(line_one, line_two): print(line_one, line_two) while file_open: try: one = file_open.next() two = file_open.next() handler(one, two) except(StopIteration): file_open.close() break
def readnumlines(file, num=2):
f = iter(file)
while True:
lines = [None] * num
for i in range(num):
try:
lines[i] = f.next()
except StopIteration: # EOF or not enough lines available
return
yield lines
# use like this
f = open("thefile.txt", "r")
for line1, line2 in readnumlines(f):
# do something with line1 and line2
# or
for line1, line2, line3, ..., lineN in readnumlines(f, N):
# do something with N lines
Работает для файлов четной и нечетной длины. Он просто игнорирует несовпадающую последнюю строку.
f=file("file")
lines = f.readlines()
for even, odd in zip(lines[0::2], lines[1::2]):
print "even : ", even
print "odd : ", odd
print "end cycle"
f.close()
Если у вас большие файлы, это неправильный подход. Вы загружаете весь файл в память с помощью readlines (). Однажды я написал класс, который читал файл, сохраняя позицию fseek каждого начала строки. Это позволяет вам получать определенные строки, не сохраняя весь файл в памяти, и вы также можете перемещаться вперед и назад.
Я вставляю его сюда. Лицензия - это общественное достояние, то есть делайте с ней все, что хотите. Обратите внимание, что этот класс был написан 6 лет назад, и с тех пор я его не трогал и не проверял. Я думаю, что это даже не файл совместимый. Будьте осторожны с покупателем . Также обратите внимание, что это излишек для вашей проблемы. Я не утверждаю, что вам обязательно стоит пойти этим путем, но у меня был этот код, и я с удовольствием делюсь им, если вам нужен более сложный доступ.
import string
import re
class FileReader:
"""
Similar to file class, but allows to access smoothly the lines
as when using readlines(), with no memory payload, going back and forth,
finding regexps and so on.
"""
def __init__(self,filename): # fold>>
self.__file=file(filename,"r")
self.__currentPos=-1
# get file length
self.__file.seek(0,0)
counter=0
line=self.__file.readline()
while line != '':
counter = counter + 1
line=self.__file.readline()
self.__length = counter
# collect an index of filedescriptor positions against
# the line number, to enhance search
self.__file.seek(0,0)
self.__lineToFseek = []
while True:
cur=self.__file.tell()
line=self.__file.readline()
# if it's not null the cur is valid for
# identifying a line, so store
self.__lineToFseek.append(cur)
if line == '':
break
# <<fold
def __len__(self): # fold>>
"""
member function for the operator len()
returns the file length
FIXME: better get it once when opening file
"""
return self.__length
# <<fold
def __getitem__(self,key): # fold>>
"""
gives the "key" line. The syntax is
import FileReader
f=FileReader.FileReader("a_file")
line=f[2]
to get the second line from the file. The internal
pointer is set to the key line
"""
mylen = self.__len__()
if key < 0:
self.__currentPos = -1
return ''
elif key > mylen:
self.__currentPos = mylen
return ''
self.__file.seek(self.__lineToFseek[key],0)
counter=0
line = self.__file.readline()
self.__currentPos = key
return line
# <<fold
def next(self): # fold>>
if self.isAtEOF():
raise StopIteration
return self.readline()
# <<fold
def __iter__(self): # fold>>
return self
# <<fold
def readline(self): # fold>>
"""
read a line forward from the current cursor position.
returns the line or an empty string when at EOF
"""
return self.__getitem__(self.__currentPos+1)
# <<fold
def readbackline(self): # fold>>
"""
read a line backward from the current cursor position.
returns the line or an empty string when at Beginning of
file.
"""
return self.__getitem__(self.__currentPos-1)
# <<fold
def currentLine(self): # fold>>
"""
gives the line at the current cursor position
"""
return self.__getitem__(self.__currentPos)
# <<fold
def currentPos(self): # fold>>
"""
return the current position (line) in the file
or -1 if the cursor is at the beginning of the file
or len(self) if it's at the end of file
"""
return self.__currentPos
# <<fold
def toBOF(self): # fold>>
"""
go to beginning of file
"""
self.__getitem__(-1)
# <<fold
def toEOF(self): # fold>>
"""
go to end of file
"""
self.__getitem__(self.__len__())
# <<fold
def toPos(self,key): # fold>>
"""
go to the specified line
"""
self.__getitem__(key)
# <<fold
def isAtEOF(self): # fold>>
return self.__currentPos == self.__len__()
# <<fold
def isAtBOF(self): # fold>>
return self.__currentPos == -1
# <<fold
def isAtPos(self,key): # fold>>
return self.__currentPos == key
# <<fold
def findString(self, thestring, count=1, backward=0): # fold>>
"""
find the count occurrence of the string str in the file
and return the line catched. The internal cursor is placed
at the same line.
backward is the searching flow.
For example, to search for the first occurrence of "hello
starting from the beginning of the file do:
import FileReader
f=FileReader.FileReader("a_file")
f.toBOF()
f.findString("hello",1,0)
To search the second occurrence string from the end of the
file in backward movement do:
f.toEOF()
f.findString("hello",2,1)
to search the first occurrence from a given (or current) position
say line 150, going forward in the file
f.toPos(150)
f.findString("hello",1,0)
return the string where the occurrence is found, or an empty string
if nothing is found. The internal counter is placed at the corresponding
line number, if the string was found. In other case, it's set at BOF
if the search was backward, and at EOF if the search was forward.
NB: the current line is never evaluated. This is a feature, since
we can so traverse occurrences with a
line=f.findString("hello")
while line == '':
line.findString("hello")
instead of playing with a readline every time to skip the current
line.
"""
internalcounter=1
if count < 1:
count = 1
while 1:
if backward == 0:
line=self.readline()
else:
line=self.readbackline()
if line == '':
return ''
if string.find(line,thestring) != -1 :
if count == internalcounter:
return line
else:
internalcounter = internalcounter + 1
# <<fold
def findRegexp(self, theregexp, count=1, backward=0): # fold>>
"""
find the count occurrence of the regexp in the file
and return the line catched. The internal cursor is placed
at the same line.
backward is the searching flow.
You need to pass a regexp string as theregexp.
returns a tuple. The fist element is the matched line. The subsequent elements
contains the matched groups, if any.
If no match returns None
"""
rx=re.compile(theregexp)
internalcounter=1
if count < 1:
count = 1
while 1:
if backward == 0:
line=self.readline()
else:
line=self.readbackline()
if line == '':
return None
m=rx.search(line)
if m != None :
if count == internalcounter:
return (line,)+m.groups()
else:
internalcounter = internalcounter + 1
# <<fold
def skipLines(self,key): # fold>>
"""
skip a given number of lines. Key can be negative to skip
backward. Return the last line read.
Please note that skipLines(1) is equivalent to readline()
skipLines(-1) is equivalent to readbackline() and skipLines(0)
is equivalent to currentLine()
"""
return self.__getitem__(self.__currentPos+key)
# <<fold
def occurrences(self,thestring,backward=0): # fold>>
"""
count how many occurrences of str are found from the current
position (current line excluded... see skipLines()) to the
begin (or end) of file.
returns a list of positions where each occurrence is found,
in the same order found reading the file.
Leaves unaltered the cursor position.
"""
curpos=self.currentPos()
list = []
line = self.findString(thestring,1,backward)
while line != '':
list.append(self.currentPos())
line = self.findString(thestring,1,backward)
self.toPos(curpos)
return list
# <<fold
def close(self): # fold>>
self.__file.close()
# <<fold
В прошлом месяце я работал над аналогичной проблемой. Я пробовал цикл while с f.readline (), а также f.readlines (). Мой файл данных невелик, поэтому я, наконец, выбрал f.readlines (), что дает мне больше контроля над индексом, в противном случае Мне нужно использовать f.seek () для перемещения вперед и назад указателя файла.
Мой случай более сложен, чем OP. Поскольку мой файл данных более гибкий в отношении того, сколько строк нужно анализировать каждый раз, поэтому Мне нужно проверить несколько условий, прежде чем я смогу проанализировать данные.
Еще одна проблема, которую я обнаружил о f.seek (), заключается в том, что она не очень хорошо обрабатывает utf-8, когда я использую codecs.open ('', 'r', 'utf-8'), (не совсем уверен в виновнике, в конце концов я отказался от этого подхода.)
Этот код Python напечатает первые две строки:
import linecache
filename = "ooxx.txt"
print(linecache.getline(filename,2))
Моя идея состоит в том, чтобы создать генератор, который считывает две строки из файла за раз и возвращает их как кортеж из двух элементов. Это означает, что вы можете затем перебирать результаты.
from cStringIO import StringIO
def read_2_lines(src):
while True:
line1 = src.readline()
if not line1: break
line2 = src.readline()
if not line2: break
yield (line1, line2)
data = StringIO("line1\nline2\nline3\nline4\n")
for read in read_2_lines(data):
print read
Если у вас нечетное количество строк, это не сработает идеально, но это должно дать вам хороший план.