OVH Cloud OVH Cloud

open en mode "a+" sous mac

12 réponses
Avatar
Sébastien Kirche
Bonjour,

Y a-t-il des utilisateurs Python sous OSX dans la salle ?

j'ai rencontré un petit problème dans un script utilisé par MacCvsX pour
ajouter une entrée dans un .cvsignore.

Le script en question ouvre le fichier en mode "a+" pour
- lire le contenu par readlines()
- ajouter un élément au tableau
- tronquer le fichier
- écrire le tableau modifié dans le fichier

Or, readlines() après l'ouverture retourne un tableau vide.
Testé ici avec Python 2.4 (#1, Feb 24 2005, 11:32:53)

J'ai corrigé le problème en ouvrant le fichier en lecture, puis en le
rouvrant ensuite en écriture, mais ce problème m'inquiète.

Comment je pourrais savoir si c'est un bug ?
L'un d'entre vous l'aurait-il rencontré ou pourrait me le confirmer ?
Merci.

--
Sébastien Kirche

10 réponses

1 2
Avatar
Guillaume Bouchard
Sébastien Kirche wrote:
Bonjour,


Bonjour,

Y a-t-il des utilisateurs Python sous OSX dans la salle ?


Non, mais je vais quand même te repondre car je pense que ton probleme
est independant de l'os.

Le script en question ouvre le fichier en mode "a+" pour
- lire le contenu par readlines()


Voila.
Mode a+, c'est à dire append. Donc des que tu as ajouté du contenu,
l'iterateur se trouve à la fin du fichier.

fp = open('ex.py','a+')
fp.readline()
'#!/usr/bin/env pythonn'



fp.write('toto')
fp.readline()
''



fp.seek(0)
fp.readline()
'#!/usr/bin/env pythonn'



fp.close()




Valable aussi pour readlines()

J'ai corrigé le problème en ouvrant le fichier en lecture, puis en le
rouvrant ensuite en écriture, mais ce problème m'inquiète.


Si cela te convient, conserve cette technique. Je n'ai jamais trop aimé
les mode read and write... C'est source de problème et souvent dû AMHA a
algo mal conçu.

--
Guillaume.



Avatar
Sébastien Kirche
Le 28 Apr 2005, Guillaume Bouchard a dit :

Le script en question ouvre le fichier en mode "a+" pour - lire le
contenu par readlines()


Voila.
Mode a+, c'est à dire append. Donc des que tu as ajouté du contenu,
l'iterateur se trouve à la fin du fichier.

fp = open('ex.py','a+')
fp.readline()
'#!/usr/bin/env pythonn'





Donc 'a+' permet bien de lire le contenu du fichier ?

fp.write('toto')
fp.readline()
''



fp.seek(0)
fp.readline()
'#!/usr/bin/env pythonn'



fp.close()




Valable aussi pour readlines()


Oui, mais non :

fp = open('/Volumes/SeKiOS9/User/dev_prj/Sage/columbia/.cvsignore', 'r')
fp.readlines()
['integr.winn', 'columbia?Datan', 'outn', 'Icon?n', 'Merge?Outn']



fp.close()




Or,
fp = open('/Volumes/SeKiOS9/User/dev_prj/Sage/columbia/.cvsignore', 'a+')
fp.readlines()
[]



fp.close()




Je n'ai pas le même comportement.

C'est donc un bug possible (?) que je veux bien signaler si je savais
comment vérifier s'il n'est pas déjà signalé/corrigé.

--
Sébastien Kirche




Avatar
Jerome
Sébastien Kirche wrote:
Le 28 Apr 2005, Guillaume Bouchard a dit :


Le script en question ouvre le fichier en mode "a+" pour - lire le
contenu par readlines()


Voila.
Mode a+, c'est à dire append. Donc des que tu as ajouté du contenu,
l'iterateur se trouve à la fin du fichier.


fp = open('ex.py','a+')
fp.readline()




'#!/usr/bin/env pythonn'



Donc 'a+' permet bien de lire le contenu du fichier ?


fp.write('toto')
fp.readline()




''

fp.seek(0)
fp.readline()




'#!/usr/bin/env pythonn'

fp.close()




Valable aussi pour readlines()



Oui, mais non :


fp = open('/Volumes/SeKiOS9/User/dev_prj/Sage/columbia/.cvsignore', 'r')
fp.readlines()




['integr.winn', 'columbia?Datan', 'outn', 'Icon?n', 'Merge?Outn']

fp.close()





Or,

fp = open('/Volumes/SeKiOS9/User/dev_prj/Sage/columbia/.cvsignore', 'a+')
fp.readlines()




[]

fp.close()





Je n'ai pas le même comportement.

C'est donc un bug possible (?) que je veux bien signaler si je savais
comment vérifier s'il n'est pas déjà signalé/corrigé.



Non, ce n'est pas un bug. Guillaume t'a expliqué ton problème déjà.

avec a tu te positionnes à la fin du fichier donc il n'y a plus rien à
lire dans le fichier ce qui explique ta liste vide.





Avatar
Sébastien Kirche
Le 28 Apr 2005, Guillaume Bouchard a formulé :

fp = open('ex.py','a+')
fp.readline()
'#!/usr/bin/env pythonn'



fp.write('toto')
fp.readline()
''



fp.seek(0)
fp.readline()
'#!/usr/bin/env pythonn'



fp.close()






Le 29 Apr 2005, Jerome s'est exprimé ainsi :

Non, ce n'est pas un bug. Guillaume t'a expliqué ton problème déjà.

avec a tu te positionnes à la fin du fichier donc il n'y a plus rien à
lire dans le fichier ce qui explique ta liste vide.


Je suis peut-être bouché, mais je ne comprends pas.

Dans son exemple que je reproduis plus haut, il ouvre bien un fichier
'ex.py' en mode a+, et à la ligne suivante readline() lui retourne bien
quelque chose non ?

--
Sébastien Kirche




Avatar
Eric Jacoboni
In article , SÈbastien Kirche
wrote:


avec a tu te positionnes à la fin du fichier donc il n'y a plus rien à
lire dans le fichier ce qui explique ta liste vide.


Je suis peut-être bouché, mais je ne comprends pas.


Il n'y a pas grand chose à comprendre :)

"a" et "a+" positionnent le curseur en fin de fichier. Un readline ne
devrait donc rien renvoyer...

% head -1 testpop3.py
import sys

% python
Python 2.3 (#1, Sep 13 2003, 00:49:11)
[GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
fp = open("testpop3.py", "a+")
fp.readline()
''



fp.close()
fp = open("testpop3.py", "r")
fp.readline()
'import sysn'







Dans son exemple que je reproduis plus haut, il ouvre bien un fichier
'ex.py' en mode a+, et à la ligne suivante readline() lui retourne bien
quelque chose non ?


Ben c'est pas normal.

--
jaco



Avatar
Sébastien Kirche
On Sat, 30 Apr 2005 09:19:38 +0200
Eric Jacoboni wrote:

| > Je suis peut-être bouché, mais je ne comprends pas.
|
| Il n'y a pas grand chose à comprendre :)
|
| "a" et "a+" positionnent le curseur en fin de fichier. Un readline ne
| devrait donc rien renvoyer...

"a" pour append, ok.

*Mais* "a+" pour read and append, je l'ai encore lu dans diverses docs
en ligne.

Tiens, je n'avais pas pu vérifier dans mon «Python en concentré», mais
p.192, au chapitre «Création d'un objet fichier avec open», paragraphe
'a+' de la section «modes des fichiers» :

«Le fichier est ouvert en lecture et écriture : toutes les méthodes de
f peuvent alors s'appliquer. Le contenu du fichier reste intact s'il
existait déjà : les données ajoutées le seront après ce qu'il
contient. Si le fichier n'existe pas, il est créé. Un appel à f.seek
n'a aucun effet si l'opération d'E/S suivante sur f est une écriture,
mais fonctionne normalement si l'opération suivante est une lecture.»

D'ailleurs sur mon Linux :
f = open("genese_internet.txt", "a+")
f.readline()
'Au début, il y avait UNIX. Enfin, pas exactement. Au début, il y



avait le Néant. Il y en a n'
f.close()




*Donc* j'en conclus que l'implémentation de Python sur OSX est buggée
pour l'accès en a+...

| [snip ton essai identique au mien sous mac]
|
| > Dans son exemple que je reproduis plus haut, il ouvre bien un
| > fichier 'ex.py' en mode a+, et à la ligne suivante readline() lui
| > retourne bien quelque chose non ?
|
| Ben c'est pas normal.

Visiblement, pas sûr.

--
Sébastien Kirche



Avatar
Eric Jacoboni
In article , SÈbastien Kirche
wrote:

«Le fichier est ouvert en lecture et écriture : toutes les méthodes de
f peuvent alors s'appliquer. Le contenu du fichier reste intact s'il
existait déjà : les données ajoutées le seront après ce qu'il
contient. Si le fichier n'existe pas, il est créé. Un appel à f.seek
n'a aucun effet si l'opération d'E/S suivante sur f est une écriture,
mais fonctionne normalement si l'opération suivante est une lecture.»


Cela ne contredit pas le fait qu'en append, on est positionné à la fin
du fichier après l'ouverture...

*Donc* j'en conclus que l'implémentation de Python sur OSX est buggée
pour l'accès en a+...


Chacun ses idées... moi j'aurais tendance à dire qu'alors ce serait le
comportement de "a+" qui serait buggé avec Python...

D'ailleurs, petit comparatif :

% irb
irb(main):001:0> fp = open "Amis.hs", "a+"
=> #<File:Amis.hs>
irb(main):002:0> fp.readline
EOFError: End of file reached
from (irb):2:in `readline'
from (irb):2
irb(main):003:0> fp.close
=> nil
irb(main):004:0> fp = open "Amis.hs", "r"
=> #<File:Amis.hs>
irb(main):005:0> fp.readline
=> "import System.Environment (getArgs)n"

--
jaco

Avatar
Sébastien Kirche
On Sat, 30 Apr 2005 12:01:37 +0200
Eric Jacoboni wrote:

| In article , SÈbastien Kirche
| wrote:
|
| > «Le fichier est ouvert en lecture et écriture : toutes les
| > méthodes de f peuvent alors s'appliquer. Le contenu du fichier
| > reste intact s'il existait déjà : les données ajoutées le seront
| > après ce qu'il contient. Si le fichier n'existe pas, il est créé.
| > Un appel à f.seek n'a aucun effet si l'opération d'E/S suivante
| > sur f est une écriture, mais fonctionne normalement si l'opération
| > suivante est une lecture.»
|
| Cela ne contredit pas le fait qu'en append, on est positionné à la fin
| du fichier après l'ouverture...

Oui, en fait ça ne précise pas où la position est censée se trouver.
Logiquement à la fin en mode append, mais a+ ?
En toute logique à mon avis, si tu cherches à lire dans un fichier même
si comptes y ajouter des données, il ne me paraît pas incongru qu'un
readline te renvoie des données.

Je n'avais pas fait le parallèle avec le C, où je n'ai jamais utilisé
d'ouverture en mode "a+".

| > *Donc* j'en conclus que l'implémentation de Python sur OSX est
| > buggée pour l'accès en a+...
|
| Chacun ses idées... moi j'aurais tendance à dire qu'alors ce serait le
| comportement de "a+" qui serait buggé avec Python...

En tout cas il y a un problème, puisque la version mac n'est pas
cohérente avec les implémentations win et linux et ne donne pas le même
résultat. À ton avis la version mac est celle qui a raison ?

|
| D'ailleurs, petit comparatif :
|
| % irb
| irb(main):001:0> fp = open "Amis.hs", "a+"
| [...]


[ ~]% irb
zsh: correct 'irb' to 'rb' [nyae]? n
zsh: command not found: irb

C'est quoi irb ? Un interpréteur ruby ?

--
Sébastien Kirche
Avatar
Sébastien Kirche
On Sat, 30 Apr 2005 12:24:17 +0200
tiissa wrote:

| Pas sûr.
| Il s'agit peut-être simplement d'un comportement non documenté.
| Je n'ai rien trouvé dans la doc disant explicitement qu'open avec le
| mode 'a+' positionne ou non le pointeur de fichier au début ou à la
| fin.

Il y a manisfetement un problème puisque python sur 3 plateformes donne
un résultat différent sur l'une d'entre elles.

| Du coup, si ton programme a besoin du pointeur au début, c'est à toi
| de l'y placer pour normaliser les éventuelles différences entre mac et
| linux. ;)

Pourquoi pas, si c'est la façon de faire.

| A noter, pour ajouter à la confusion, que la page de manuel de fopen
| sur mon linux précise que le pointeur est positionné à la fin.
| Or un test avec l'open de python montre qu'il semble être au début du
| fichier.
| Par contre, je n'ai rien trouvé dans la source du open/file de python
| qui en change la position.
| Du coup, un petit programme C plus tard [1], j'ai l'impression que
| c'est simplement le fopen qui ne serait pas en accord avec le man (et
| une norme ?) et que ce ne serait pas la faute de python.
| [snip l'exemple c]

Je n'avais pas fait le parallèle avec fopen du c. Je fais du c tous les
jours, mais avec des couches d'abstraction et je ne programme pas
d'accès fichier directement.

Mais àma, il y a un truc qui cloche quelque part...

--
Sébastien Kirche
Avatar
Eric Jacoboni
In article , SÈbastien Kirche
wrote:


Oui, en fait ça ne précise pas où la position est censée se trouver.
Logiquement à la fin en mode append, mais a+ ?
En toute logique à mon avis, si tu cherches à lire dans un fichier même
si comptes y ajouter des données, il ne me paraît pas incongru qu'un
readline te renvoie des données.


Quand tu utilises "r+", "w+" ou "a+", il faut plus voir la lettre comme
une indication de la position initiale après ouverture, et le "+" comme
une autorisation du mode "update", àmha... Bref, je me garderai bien de
supposer que ces deux significations sont synchrones (genre, "a+" mode append ET mode read...) : a+, pour moi, c'est mode "append" avec,
/comme bonus/, la possibilité de lire, mais à condition de le gérer
soi-même..

Le man de fopen dit entre autres :

"When a file is opened with update mode ( '+' as the second or third
character in the mode argument), both input and output may be performed
However, the application shall ensure that output is not directly
followed by input without an intervening call to fflush() or to a
file positioning function ( fseek(), fsetpos(), or rewind()), and input
is not directly followed by output without an intervening call to
a file positioning function, unless the input operation encounters
end-of-file."

Donc, en gros, avec le mode +, c'est à toi de gérer le curseur pour que
l'instruction soit cohérente et, si on suppose que le mode majeur "a"
positionne à la fin, il n'est pas cohérent de vouloir lire
immédiatement après avoir ouvert un fichier... Regarde ce que ça
donnerait en algo :

Début
Ouvrir le fichier en se positionnant à la fin;
Lire une ligne;
Fin

Un peu space, n'est-il pas ?

Le fait que tu ais mis "a+" ne permet pas à fopen/whatever de savoir ce
que tu feras après : une lecture ou une écriture. Il se positionne à la
fin parce que tu as mis 'a', tu aurais mis 'r' il se serait positionné
au début et c'est bien logique.

Après, ce que dit la norme C, ce que dit Python (ou ce qu'ils ne disent
pas), je m'en fous un peu ;) c'est pour moi une histoire de logique et
je ne code jamais en utilisant des tricks qui ne me sembleraient pas
logiques...

Je n'avais pas fait le parallèle avec le C, où je n'ai jamais utilisé
d'ouverture en mode "a+".


Ben moi ça m'est arrivé, mais toujours en utilisant des fseek(). Des
experts pourront sûrement t'en dire plus sur fclc.

C'est quoi irb ? Un interpréteur ruby ?


Oui, sous Mac OS, il est dans /usr/bin (j'utilise le port DP, qui est
bien plus récent).

--
jaco

1 2