def file_observer(population, num_generations, num_evaluations, args):
    """Print the output of the evolutionary computation to a file.
    
    This function saves the results of the evolutionary computation
    to two files. The first file, which by default is named 
    'inspyred-statistics-file-<timestamp>.csv', contains the basic
    generational statistics of the population throughout the run
    (worst, best, median, and average fitness and standard deviation
    of the fitness values). The second file, which by default is named
    'inspyred-individuals-file-<timestamp>.csv', contains every individual
    during each generation of the run. Both files may be passed to the
    function as keyword arguments (see below).
    
    The format of each line of the statistics file is as follows::
    
       generation number, population size, worst, best, median, average, standard deviation

    The format of each line of the individuals file is as follows::
    
       generation number, individual number, fitness, string representation of candidate
    
    .. note::
    
       This function makes use of the ``inspyred.ec.analysis.fitness_statistics`` 
       function, so it is subject to the same requirements.
    
    .. Arguments:
       population -- the population of Individuals
       num_generations -- the number of elapsed generations
       num_evaluations -- the number of candidate solution evaluations
       args -- a dictionary of keyword arguments

    Optional keyword arguments in args:
    
    - *statistics_file* -- a file object (default: see text)
    - *individuals_file* -- a file object (default: see text) 
    
    """
    try:
        statistics_file = args['statistics_file']
    except KeyError:
        statistics_file = open('inspyred-statistics-file-{0}.csv'.format(time.strftime('%m%d%Y-%H%M%S')), 'w')
        args['statistics_file'] = statistics_file
    try:
        individuals_file = args['individuals_file']
    except KeyError:
        individuals_file = open('inspyred-individuals-file-{0}.csv'.format(time.strftime('%m%d%Y-%H%M%S')), 'w')
        args['individuals_file'] = individuals_file

    stats = inspyred.ec.analysis.fitness_statistics(population)
    worst_fit = stats['worst']
    best_fit = stats['best']
    avg_fit = stats['mean']
    med_fit = stats['median']
    std_fit = stats['std']
    
    statistics_file.write('{0}, {1}, {2}, {3}, {4}, {5}, {6}\n'.format(num_generations, len(population), worst_fit, best_fit, med_fit, avg_fit, std_fit))
    for i, p in enumerate(population):
        individuals_file.write('{0}, {1}, {2}, {3}\n'.format(num_generations, i, p.fitness, str(p.candidate)))
    statistics_file.flush()
    individuals_file.flush()
Print the output of the evolutionary computation to a file.
    
    This function saves the results of the evolutionary computation
    to two files. The first file, which by default is named 
    'inspyred-statistics-file-<timestamp>.csv', contains the basic
    generational statistics of the population throughout the run
    (worst, best, median, and average fitness and standard deviation
    of the fitness values). The second file, which by default is named
    'inspyred-individuals-file-<timestamp>.csv', contains every individual
    during each generation of the run. Both files may be passed to the
    function as keyword arguments (see below).
    
    The format of each line of the statistics file is as follows::
    
       generation number, population size, worst, best, median, average, standard deviation

    The format of each line of the individuals file is as follows::
    
       generation number, individual number, fitness, string representation of candidate
    
    .. note::
    
       This function makes use of the ``inspyred.ec.analysis.fitness_statistics`` 
       function, so it is subject to the same requirements.
    
    .. Arguments:
       population -- the population of Individuals
       num_generations -- the number of elapsed generations
       num_evaluations -- the number of candidate solution evaluations
       args -- a dictionary of keyword arguments

    Optional keyword arguments in args:
    
    - *statistics_file* -- a file object (default: see text)
    - *individuals_file* -- a file object (default: see text)