8
votes

Pourquoi le contexte traîne-t-il après une déclaration?

J'aimerais savoir pourquoi un objet de fichier ouvert à l'aide de avec code> instruction ou dans un bloc, reste dans la portée de la sortie. Sont code> les objets jamais nettoyés?

>>> with open('test.txt','w') as f:
...     f.write('test')
...
>>> f
<closed file 'test.txt', mode 'w' at 0x00E014F0>
>>> f.close()


>>> if True:
...     fal = open('demo.txt','w')
...     fal.write('stuff')
...     fal.close()
...
>>> fal
<closed file 'demo.txt', mode 'w' at 0x00E015A0>


1 commentaires

Voici PEP 343 pour une lecture légère.


5 Réponses :


0
votes

L'objet de fichier, comme n'importe quel autre objet, "se bloque" pendant la durée de votre programme, jusqu'à ce qu'il soit supprimé (son __ del __ est appelé).

del f causera f être déposé par le collecteur des ordures de Python. Cela se produit automatiquement lorsque vous quittez une portée, votre script se termine ou dans votre exemple, la session d'interprétation se termine.


6 commentaires

C'est trompeur. Python supprimera l'objet lorsqu'il n'y a plus de références, et del f ne supprimera qu'une référence à l'objet référencé par f .


Droite, mais je faisais référence à del f dans le cadre de son exemple, où il n'en a qu'une référence (il pouvait lire dans les subtilités du mécanisme de comptage de référence de Python GC pour une explication plus profonde).


Si tel est le cas, alors le ' EXIT WRAPPER qui fait partie de la déclaration avec (), appelez del , je ne comprends pas comment scoper la variable à l'intérieur de la déclaration , ne cause pas qu'il soit complètement nettoyé. Dans mon exemple, il n'y avait plus de références à 'F'. Il a été déclaré juste dans la déclaration 'avec ()'


__ del __ () n'est pas nécessairement invoqué, lorsque des objets sont supprimés. La simple existence de ces procédés dans l'espace de noms de classe peut en fait empêcher l'objet d'être recueillis à la poubelle.


@pyinthéthesky: Cela ne peut pas (vous ne pouvez pas modifier la portée de l'appelant, qui est une très bonne chose BTW!) Et il y a des moments où vous ne le voulez pas. Et même si vous n'en avez pas besoin, cela n'a pas d'importance. Vous faites deux mauvaises hypothèses: (1) que GC de l'objet est requis pour le nettoyage (tout le nettoyage est dans __ sortie __ , seule la mémoire du gestionnaire de contexte n'est pas récupérée) et (2) que < Code> avec a sa propre portée (ce n'est pas - dans votre exemple f est toujours autour à cause de cela).


@delnan: Seulement 2: P, merci pour les clarifications. À la fin de la journée, j'aimerais pouvoir faire F.Open () si cela va rester.



4
votes

Le nom restera dans la portée jusqu'à ce que vous quittiez la portée.

Si vous souhaitez que l'objet nettoyé, attribuez une valeur différente au nom, comme xxx p> Cela ne ferme pas le fichier!

C'est une bonne habitude de rendre les scopes limitées en structurant le programme dans les fonctions (et éventuellement de cours). Cela le rend plus lisible et fait des objets non liés (aucun nom dans la portée qui fait référence à l'objet) eureux pour la collecte des ordures.

Ce n'est généralement pas un problème lorsque vous utilisez l'invite cependant :)


3 commentaires

Le fichier est fermé. Même REC vous dit que. Mais un fichier fermé ne supprime pas la poignée et rend comme par magie toutes les références disparaissent. Sinon bonne réponse et toucher réellement le problème de la portée, donc +1.


@delnan dans ce cas c'est. Je voulais juste expliciter qu'un fichier disparaisse du contexte ne le ferme pas nécessairement.


Lorsqu'il est utilisé dans un avec le bloc , est sera fermé à moins que l'interprète se bloque. Mais oui, il suffit de retirer une référence pour cela ne le fera généralement pas fermer.



0
votes

avec instruction appelle la méthode __ de la classe de fichier __ [qui, dans le cas des fichiers, les ferme]. Il ne supprime pas l'objet; Il est nettoyé uniquement lorsque vous le nettoyez explicitement ou fermez le programme / interprète.


1 commentaires

... ce qui serait asynchronisé avec GC de toute façon. Pour développer, la variable est toujours autour parce que avec n'introduit pas sa propre portée.



2
votes

avec et si ne crée pas de nouvelle portée, les variables locales ne sont créées que dans les fonctions, les classes et les modules. Voir Quelle est la portée d'une variable Python Déclaré dans une déclaration IF?


0 commentaires

16
votes

dans Python NEW SCOPES (AKA NAMES ESPACES) sont uniquement créés pour des modules, des classes et des fonctions, mais pas pour une autre déclaration, surtout pas pour avec et si blocs. Les identificateurs liés dans le corps de avec ou pour sont par conséquent liés dans la portée de l'environnement la plus interne, qui est la portée du niveau supérieur de l'interprète interactif dans votre cas. Les identifiants sont liés dans une portée tant que cette portée est valide, ou jusqu'à ce qu'elles soient explicitement supprimées de la portée (en utilisant del comme dans del fal ).

Les objets ne peuvent être nettoyés que lorsqu'ils ne sont plus référencés. Le moment réel, dans lequel cet objet est vraiment nettoyé, n'est cependant pas défini. Python utilise la collecte des ordures pour la gestion de la mémoire et n'aborce pas une stratégie spécifique. Dans CPPHON, qui utilise le comptage de référence, les objets sont immédiatement nettoyés, une fois la dernière référence expirée. Des implémentations alternatives telles que PYPY ou Jython utilisent des collecteurs de déchets plus avancés, qui nettoient des objets non référencés à des moments arbitraires.

Cela signifie que dans votre exemple les objets liés à f et fal sont basciels jamais nettoyés, car la portée de l'interprète interactif existe naturellement naturellement Tant que l'interpeter est en cours d'exécution. Méfiez-vous cependant que ce n'est pas vraiment un problème, car ils sont néanmoins correctement fermés et ne réclament plus aucune ressource de dossier, mais seulement une certaine mémoire.


2 commentaires

Merci pour la réponse bien plainte.


Pour être clair, ils consomment encore des ressources, mais pas la ressource de fichiers.