[Python-es] os.walk( ) con timeout

Chema Cortes pych3m4 en gmail.com
Vie Jun 12 22:09:33 CEST 2015


El 12 de junio de 2015, 2:58, Jose Caballero <jcaballero.hep en gmail.com>
escribió:

>
>
>
>
> On Jun 11, 2015, at 20:23, Chema Cortes <pych3m4 en gmail.com> wrote:
>
>
>
> El 11 de junio de 2015, 16:06, Jose Caballero <jcaballero.hep en gmail.com>
> escribió:
>
>> [Pido perdon por adelantado por la ausencia de tildes. Teclado americano]
>>
>> Hola,
>>
>> me preguntaba si alguien sabria como hacer uso de os.walk( ) para
>> recorrer un "subtree" en el sistema de ficheros, pero con un timeout.
>> La razon para un timeout es, por ejemplo, para no quedarse esperando
>> para siempre si se trata de un sistema de ficheros montado (tipo AFS o
>> NFS) y el "server" no responde.
>>
>
> Una forma eficaz para evitar bloqueos en tu aplicación es usar "futures".
> En python3 vienen ya en la librería estándar y también de serie en anaconda:
>
> https://docs.python.org/3.4/library/concurrent.futures.html
> https://pypi.python.org/pypi/futures/
>
>
>
>
> Hola Chema,
>
> No conozco "futures", me lo tengo que mirar.
> Mi único 'constrain' es que estoy atado a python 2.6. No sé si será un
> problema. Lo sabré cuando me lo mire.
>

'futures' ha sido llevado de python3 a python 2.7 y 2.6. Lo deberías poder
usar sin problemas.


He estado haciendo unas pruebas para ver hasta era práctico. No sé si te
funcionará en tu caso, ya que los errores del sistema de ficheros
posiblemente bloqueen a todo el proceso.

En este código he intentado similar los timeouts. Se obtenien los
resultados a medida que los ficheros terminan de procesarse. Algunos
ficheros sufren aleatoriamente un retardo entre 1 y 10 segundos, y aparecen
al final del proceso precedidos por tantos asteriscos como segundos se han
retrasado. Si algún fichero supera el timeout de 8 segundos, se para todo
proceso.


from __future__ import print_function

import os
from os.path import join, getsize
from concurrent.futures import (ThreadPoolExecutor,
                                ProcessPoolExecutor,
                                TimeoutError,
                                as_completed)
from itertools import islice
import time
from random import random


def proc_file(root, dirs, files):

    try:
        size = sum(getsize(join(root, name)) for name in files)
        num = len(files)
        res = "{:8} bytes en {:3} ficheros de '{}'".format(size, num, root)

        # simulación de timeouts
        if random() > 0.9:
            espera = 10*random()
            time.sleep(espera)
            res = "*"*int(espera) + res

    except:

        res = "ERROR de acceso"

    return res


def main():

    dir_input = "/home"

    pool = ThreadPoolExecutor(40)
#    pool = ProcessPoolExecutor()

    with pool as ex:

        futures = (ex.submit(proc_file, root, dirs, files)
                    for (root, dirs, files) in os.walk(dir_input))

        while True:

            # Para evitar sobrecargar el proceso,
            # el iterador se consume en chunks de 100 elementos
            print("\n\n----------- NUEVO CHUNK -------------\n")
            chunk = list(islice(futures, 100))
            if len(chunk)==0:
                break

            try:
                for future in as_completed(chunk, timeout=8):
                    print(future.result())
            except TimeoutError:
                print("\n### ERROR: timeout exception\n")
                break

if __name__ == '__main__':
    main()
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20150612/2e7dc433/attachment.html>


Más información sobre la lista de distribución Python-es