Pergunta

This is a follow up to my previous question (text file reduction with randomization in Python). Was modifying to run through multiple reductions, but only the first output file contains reductions, the following 3 files are zero size. This must be something obvious I am not seeing...

#!/usr/bin/env python
import random
import sys
from itertools import chain, groupby

def choose_random(iterator, fraction, random=random.random):
    """Lazy analog of:

        L = list(iterator)
        k = int(len(L) * fraction + .5) or 1 # get at least one
        result = random.sample(L, k)

    Note: this function doesn't randomize the order of elements
          that would require to keep selected elements in memory
          and number of output elements is not exactly k
    """
    # always yield at least one item if input is not empty
    item = next(iterator)
    it = (x for x in chain([item], iterator) if random() < fraction)
    for x in chain([next(it, item)], it):
        yield x

def getkey(line):
    return line.split("\t")[3] # 4th column

reductions = [0.25, 0.50, 0.75, 1]
filename = "foo"
outfile = [open("-".join([x, filename]), "w") for x in map(str, reductions)]

try:
    with open(filename, "r") as f:
        for ln, k in enumerate(map(float, reductions)):
            for key, group in groupby(f, key=getkey):
                outfile[ln].writelines(choose_random(group, fraction=k))

finally:
    for f in outfile:
        f.close()

output shows up like this (file 0.25-foo contains correct reduction, the rest are empty):

-rw-r--r--  1 staff  staff   53326048 Mar 27 03:42 0.25-foo
-rw-r--r--  1 staff  staff          0 Mar 27 03:42 0.5-foo
-rw-r--r--  1 staff  staff          0 Mar 27 03:42 0.75-foo
-rw-r--r--  1 staff  staff          0 Mar 27 03:42 1-foo
Foi útil?

Solução

You open foo once, but try to iterate over it four times. By the end of the first reduction, you're at the end of file. Either reopen it:

try:
    for ln, k in enumerate(map(float, reductions)):
        with open(filename, "r") as f:
            for key, group in groupby(f, key=getkey):
                outfile[ln].writelines(choose_random(group, fraction=k))

finally:
    for f in outfile:
        f.close()

or rewind after each reduction:

try:
    with open(filename, "r") as f:
        for ln, k in enumerate(map(float, reductions)):
            for key, group in groupby(f, key=getkey):
                outfile[ln].writelines(choose_random(group, fraction=k))
            f.seek(0)

finally:
    for f in outfile:
        f.close()

I'd open both files at one point:

reductions = [0.25, 0.50, 0.75, 1.0]
filename = "foo"

for fraction in reductions:
    with open(filename, "r") as f, open('%s-%s' % (fraction, filename), 'w') as outfile:
        for key, group in groupby(f, key=getkey):
            outfile.writelines(choose_random(group, fraction=fraction))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top