Comment lire un fichier sans retour à la ligne?

374

En Python, appeler

temp = open(filename,'r').readlines()

résulte en une liste dans laquelle chaque élément est une ligne du fichier. C'est un peu stupide mais quand même: readlines()écrit également un caractère de nouvelle ligne dans chaque élément, ce que je ne souhaite pas.

Comment puis-je l'éviter?

Yotam
la source
4
Bande Utilisation: [l.strip('\n\r') for l in temp]. Ou même rstrip. Et depuis l'itération ici, cela peut être in openau lieu de in temp.
gorlum0
11
Je serais bien si en Python 3 il y avait une valeur pour définir l' newlineargument ouvert à ces nouvelles lignes traînantes.
jxramos

Réponses:

555

Vous pouvez lire le fichier entier et les lignes de séparation en utilisant str.splitlines:

temp = file.read().splitlines()

Ou vous pouvez dépouiller la nouvelle ligne à la main:

temp = [line[:-1] for line in file]

Remarque: cette dernière solution ne fonctionne que si le fichier se termine par une nouvelle ligne, sinon la dernière ligne perdra un caractère.

Cette hypothèse est vrai dans la plupart des cas ( en particulier pour les fichiers créés par les éditeurs de texte, qui souvent font ajouter une nouvelle ligne de fin de toute façon).

Si vous voulez éviter cela, vous pouvez ajouter une nouvelle ligne à la fin du fichier:

with open(the_file, 'r+') as f:
    f.seek(-1, 2)  # go at the end of the file
    if f.read(1) != '\n':
        # add missing newline if not already present
        f.write('\n')
        f.flush()
        f.seek(0)
    lines = [line[:-1] for line in f]

Ou une alternative plus simple est à stripla place de la nouvelle ligne:

[line.rstrip('\n') for line in file]

Ou même, bien qu'assez illisible:

[line[:-(line[-1] == '\n') or len(line)+1] for line in file]

Ce qui exploite le fait que la valeur de retour de orn'est pas un booléen, mais l'objet évalué comme vrai ou faux.


La readlinesméthode est en fait équivalente à:

def readlines(self):
    lines = []
    for line in iter(self.readline, ''):
        lines.append(line)
    return lines

# or equivalently

def readlines(self):
    lines = []
    while True:
        line = self.readline()
        if not line:
            break
        lines.append(line)
    return lines

Depuis, readline()la nouvelle ligne la readlines()conserve également .

Remarque: pour la symétrie de readlines()la writelines()méthode n'ajoute pas de fin de ligne, f2.writelines(f.readlines())produit donc une copie exacte de fin f2.

Bakuriu
la source
1
Notez que [line.rstrip('\n') for line in file]cela supprimera plus d'un suivi \n.
Wes Turner
1
Plus simplement, [line[:-(line[-1] == '\n') or len(line)+1] for line in file]pourrait plutôt l'être [line[:-(line[-1] == '\n') or None] for line in file].
Wes Turner
10
Ces solutions lisent l'intégralité du fichier en mémoire. Changer les crochets d'une compréhension de liste en parenthèses crée une expression de générateur qui vous permet d'itérer sur le fichier une ligne à la fois: for line in (x.strip() for x in f):
Joseph Sheedy
2
@velotron Ce n'est pas vraiment le but de la question / réponse. Aussi: gardez à l'esprit que withles fichiers sont fermés à la fin du bloc, ce qui signifie que vous ne pouvez pas faire with open(...) as f: lines = (line for line in f)et utiliser en linesdehors de withcar vous obtiendrez une erreur d'E / S. Vous pouvez être paresseux en utilisant un genexp, mais vous devez le consommer avant de fermer le fichier.
Bakuriu
@WesTurner. Mais il n'y aura pas plus d'un saut de ligne de fin. La nouvelle ligne supplémentaire fera partie de la prochaine ligne vide
Mad Physicist
38
temp = open(filename,'r').read().split('\n')
vivek
la source
14
Que se passerait-il avec les \r\nnouvelles lignes? ;)
Wolph
26
Python gère automatiquement les sauts de ligne universels, donc .split('\n')se divise correctement, indépendamment de la convention de retour à la ligne. Il serait important que vous lisiez le fichier en mode binaire.Dans ce cas, il splitlines()gère les sauts de ligne universels alors que ce split('\n')n'est pas le cas.
Bakuriu
7
Et il y a toujours os.linesep:)
askewchan
1
@LarsH, cela aiderait dans certaines circonstances, sur les \r\nterminaisons de ligne de mon système ne sont pas converties en \n, qu'elles soient lues en texte ou en binaire, donc os.linesepfonctionnerait là où \ncela ne fonctionne pas. Mais splitlinesc'est clairement le meilleur choix, dans le cas où vous mentionnez où le fichier ne correspond pas au système d'exploitation. Vraiment, je l'ai surtout mentionné au cas où les gens qui regardaient cette discussion n'étaient pas au courant de son existence.
askewchan
1
@askewchan Vous utilisez peut-être une version obsolète de Python. Je crois qu'à partir de Python 3, les sauts de ligne universels sont activés par défaut, c'est \r\n-à- dire qu'ils seraient convertis pour les fichiers texte même lorsque vous utilisez Linux.
Arthur Tacca du
13

un autre exemple:

Lecture du fichier une ligne à la fois. Suppression des caractères indésirables à partir de la fin de la chaînestr.rstrip(chars)

with open(filename, 'r') as fileobj:
    for row in fileobj:
        print( row.rstrip('\n') )

voir aussi str.strip([chars])etstr.lstrip([chars])

(python> = 2.0)

O-9
la source
10
temp = open(filename,'r').read().splitlines()
Marcel
la source
5
Êtes-vous sûr que cela ferme le fichier? Je pense que ce n'est pas le cas, donc ce n'est pas vraiment un
vol simple
9

Je pense que c'est la meilleure option.

temp = [line.strip() for line in file.readlines()]
RENZO
la source
8
Cette solution supprime également les espaces de début et de fin, ce qui n'est pas prévu.
Roland Illig
Mais la compréhension est vraiment sympa. Au moins avec Python 3, on peut utiliser temp = [line.rstrip() for line in file.readlines()]pour obtenir ce que les notes @Roland_Illig sont destinées.
bballdave025
Si vous allez parcourir toutes les lignes, pourquoi ne pas le faire paresseusement? Avec .readlines(), vous effectuez deux fois l'itération sur l'ensemble du fichier.
AMC
1

Essaye ça:

u=open("url.txt","r")  
url=u.read().replace('\n','')  
print(url)  
Nitesh Soni
la source
4
Bien que cet extrait de code puisse résoudre la question, y compris une explication aide vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondrez à la question pour les lecteurs à l'avenir, et ces personnes pourraient ne pas connaître les raisons de votre suggestion de code. Essayez également de ne pas surcharger votre code avec des commentaires explicatifs, car cela réduit la lisibilité du code et des explications!
Au revoir StackExchange
Je ne vois pas pourquoi quelqu'un devrait utiliser cela sur certaines des solutions alternatives.
AMC
-1
my_file = open("first_file.txt", "r")
for line in my_file.readlines():
    if line[-1:] == "\n":
        print(line[:-1])
    else:
        print(line)
my_file.close() 
Necriss
la source
3
Veuillez ajouter quelques explications afin qu'elles soient utiles aux autres.
samuellawrentz
Vous devez utiliser un gestionnaire de contexte pour gérer l'objet fichier et parcourir directement le fichier. En utilisant .readlines()comme ceci, vous parcourez efficacement le fichier entier deux fois.
AMC
-2
import csv

with open(filename) as f:
    csvreader = csv.reader(f)
    for line in csvreader:
         print(line[0])
srus
la source
2
Mais que faire si la ligne contient une virgule?
gilch
-8
def getText():
    file=open("ex1.txt","r");

    names=file.read().split("\n");
    for x,word in enumerate(names):
        if(len(word)>=20):
            return 0;
            print "length of ",word,"is over 20"
            break;
        if(x==20):
            return 0;
            break;
    else:
        return names;


def show(names):
    for word in names:
        len_set=len(set(word))
        print word," ",len_set


for i in range(1):

    names=getText();
    if(names!=0):
        show(names);
    else:
        break;
user4730171
la source