Disculpas de antemano: soy nuevo en la codificación, así que esta es probablemente una pregunta tonta.

Estoy tratando de escanear un archivo de texto local (descargué el texto de http://norvig.com/big.txt) y luego lea e imprima líneas aleatorias de este archivo en una lista.

Sin embargo, no quiero imprimir ninguna línea vacía, solo las líneas que contienen texto.

Así que intenté usar el siguiente código:

import random

with open('C:\\big.txt', 'r') as f:
    while True:
        random_line_str = random.choice(f.readlines())
        random_line_lst = random_line_str.split()
        if random_line_lst != []:
            print(random_line_lst)
            break

Entonces esto funciona bien para líneas que contienen texto. Pero también ocasionalmente escupe el siguiente error:

Traceback (most recent call last):
  File "C:\Python\lib\random.py", line 253, in choice
    i = self._randbelow(len(seq))
  File "C:\Python\lib\random.py", line 230, in _randbelow
    r = getrandbits(k)          # 0 <= r < 2**k
ValueError: number of bits must be greater than zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:/PycharmProjects/Testing/Test.py", line 5, in <module>
    random_line_str = random.choice(f.readlines())
  File "C:\Python\lib\random.py", line 255, in choice
    raise IndexError('Cannot choose from an empty sequence')
IndexError: Cannot choose from an empty sequence

No tengo ni idea de lo que está pasando aquí para ser honesta ...

¿Alguna idea de cómo puedo evitar que esto suceda y solo devuelva líneas que contienen texto?

¡Salud!

0
chewflow 10 may. 2016 a las 06:46

3 respuestas

La mejor respuesta

Esta línea no verifica si el elemento es una lista vacía, verifica si el elemento está en una lista vacía, lo que siempre será falso (lo que significa que item not in [] siempre será verdadero):

if random_line_lst not in []:

Lo que puede hacer es que bool([]) es falso, solo haga lo siguiente:

if random_line_lst:

Si es probable que verifique explícitamente una lista vacía, use el operador !=.

if random_line_lst != []:

Usando lo anterior, su código se convierte en:

import random

with open('C:\\big.txt', 'r') as f:
    while True:
        random_line_str = random.choice(f.readlines())
        random_line_lst = random_line_str.split()
        if random_line_lst:
            print(random_line_lst)
            break

EDITAR

Para random.choice, el problema es que está llamando repetidamente a random.choice en f.readlines(). Readlines solo devuelve cada línea en la primera llamada, luego solo devolverá una secuencia vacía. random.choice no puede seleccionar un elemento de una secuencia vacía. Una mejor estrategia es esta:

import random

with open('C:\\big.txt', 'r') as f:
    lines = f.readlines()
    while True:
        random_line_str = random.choice(lines)
        random_line_lst = random_line_str.split()
        if random_line_lst:
            print(random_line_lst)
            break

O, si puede separarse de la aleatoriedad, use lo siguiente:

with open('C:\\big.txt', 'r') as f:
    for line in f:
        line_lst = line.split()
        if line_lst:
            print(line_lst)
            break
3
Alexander Huszagh 10 may. 2016 a las 04:00

imprimir si random_line_lst no es []

No, no estás comprobando eso. Más bien está comprobando si la variable de lista random_line_lst no existe en [], lo cual siempre es cierto ya que [] está vacío y no existe nada en él. Entonces la comprobación if random_line_lst not in []: no es correcta.

En lugar de que necesite verificar:

if len(random_line_lst) > 0:

O un atajo (y una mejor forma) es verificar

if random_line_lst:

Ya que las listas vacías son falsas.

Además, no puede llamar a f.readlines() siempre dentro del bucle. Debe mantener esas líneas en una variable antes de que comience el ciclo, de lo contrario obtendrá un IndexError la próxima vez que se ejecute el ciclo. La razón es que en la primera llamada de f.readlines() se lee todo el archivo, y en la siguiente posición del archivo de la llamada ya está al final del archivo, por lo que la próxima lectura devolverá la lista vacía, a menos que busque poner a cero la posición del archivo. Para su caso, simplemente puede mover la llamada readlines() fuera de bucle.

with open('C:\\big.txt', 'r') as f:
    lines = f.readlines()
    while True:
        random_line_str = random.choice(lines)
2
taskinoor 10 may. 2016 a las 04:02

Creo que puede utilizar el método strip en esta situación, porque incluso si la línea está vacía, seguirá teniendo el retorno de carro asociado a esa línea. Para que pueda verificar la siguiente condición

line.strip() != '' #checking if the line is empty by removing the Carriage return 

with open('fdf.txt','r') as f:
     for line in f:
        if line.strip() != '' :
            print(line)

Espero que ayude.

2
Strik3r 10 may. 2016 a las 05:33