IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Problème de copie d'un objet psycopg2 via deepcopy


Sujet :

Python

  1. #1
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 850
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 850
    Billets dans le blog
    1
    Par défaut Problème de copie d'un objet psycopg2 via deepcopy
    Bonjour à tous

    J'ai eu récemment un souci en voulant copier un objet perso via copy.deepcopy lorsque cet objet contenait lui-même une connexion vers une bdd Postgres via psycopg2. La connexion est perdue dans l'objet copié

    Exemple minimaliste
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import psycopg2
    import copy
     
    class cToto(object):
    	def __init__(self):
    		print "init"
    		self.bdd=psycopg2.connect(
    			host="localhost",
    			dbname="ma_bdd",
    			user="postgres",
    		)
     
    	def __str__(self):
    		return "%s" % repr(self)
     
    	def copy(self):
    		other=copy.deepcopy(self)
    		#other.bdd=self.bdd
    		return other
    # cToto()
     
    a=cToto()
    print a, type(a), a.bdd
    b=a.copy()
    print b, type(b), b.bdd

    b est un objet copié à partir de a. Ben lorsque j'affiche b.bdd, j'ai une erreur de segmentation.

    En revanche, si je décommente la ligne qui copie la connexion bdd, je n'ai plus d'erreur.

    Je voulais savoir si quelqu'un avait déjà vu un truc similaire et s'il avait une explication.

    Merci

    PS: je suis sous Python v2.6.6 sur une Debian Squeeze
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 772
    Par défaut
    Salut,
    Espérez vous que cela puisse fonctionner?
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 850
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 850
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,
    Espérez vous que cela puisse fonctionner?
    - W
    Salut

    Je sens comme un certain sarcasme dans cette question. Toutefois, mes connaissances limitées sur le fonctionnement de deepcopy et/ou de psycopg2 ne me permettent pas d'en apprécier la substantifique moelle.
    Cependant j'ai fait mienne une maxime qui dit que celui qui pose une question reste stupide 2 mn tandis que celui qui n'en pose pas reste stupide toute sa vie donc je vais répondre comme si ton sarcasme n'en était pas un en disant que oui j'espère que cela fonctionne. Surtout que si je décommente la ligne other.bdd=self.bdd alors cela fonctionne réellement. Je peux alors taper dans ma bdd depuis a ou b (lister mes tables, insérer/modifier/supprimer des lignes) sans souci (apparent).

    C'est encore flou mais je pense que la connexion psycopg2.connect() crée dans a.bdd une instance impalpable qui ne peut donc être copié dans b par deepcopy(). Me faut alors forcer cette copie pour que b.bdd reçoive la même instance.

    J'ai d'ailleurs tapé un exemple similaire pour vérifier cette théorie
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import copy
     
    class cToto(object):
    	def __init__(self):
    		print "init"
    		self.file=open("/etc/passwd", "r")
     
    	def __str__(self):
    		return "%s" % repr(self)
     
    	def copy(self):
    		other=copy.deepcopy(self)
    		#other.file=self.file
    		return other
    # cToto()
     
    a=cToto()
    print a, type(a), a.file
    b=a.copy()
    print b, type(b), b.file
    Voici ce que ça donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    moi@debian:~$ ./cp2.py 
    init
    <__main__.cToto object at 0xb70f174c> <class '__main__.cToto'> <open file '/etc/passwd', mode 'r' at 0xb73391d8>
    <__main__.cToto object at 0xb70f18ac> <class '__main__.cToto'> <closed file '<uninitialized file>', mode '<uninitialized file>' at 0xb7339180>
    Et voici ce que ça donne si je décommente la ligne other.file=self.file...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    moi@debian:~$ ./cp2.py 
    init
    <__main__.cToto object at 0xa20b72c> <class '__main__.cToto'> <open file '/etc/passwd', mode 'r' at 0xb746e1d8>
    <__main__.cToto object at 0xa20b88c> <class '__main__.cToto'> <open file '/etc/passwd', mode 'r' at 0xb746e1d8>
    Est-ce que mon hypothèse est bonne ?
    Merci
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour Sve@r,

    L'objet Python est bien copier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    #
    import copy
     
     
    class cToto(object):
        def __init__(self):
            print "init"
            self.fd = open("/etc/passwd", "r")
     
        def __str__(self):
            return "%s" % repr(self)
     
        def copy(self):
            other = copy.deepcopy(self)
            print 'deepcopy :', other.fd
            print 'In copy. self.fd is other.fd', self.fd is other.fd
            other.fd = self.fd
            print 'other.fr :', other.fd
            print 'In copy. self.fd is other.fd', self.fd is other.fd
            return other
     
    a = cToto()
    b = a.copy()
    print 'a.fd == b.fd', a.fd == b.fd
    print 'a.fd is b.fd', a.fd is b.fd
    Sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    patrice@Zeus:~/Bureau$ /usr/bin/python2.7 testico.py 
    init
    deepcopy : <closed file '<uninitialized file>', mode '<uninitialized file>' at 0xb76a4440>
    In copy. self.fd is other.fd False
    other.fr : <open file '/etc/passwd', mode 'r' at 0xb76a43e8>
    In copy. self.fd is other.fd True
    a.fd == b.fd True
    a.fd is b.fd True
    Mais la référence perdue.
    Avec other.fd = self.fd vous faite juste une copy toute simple de l'objet. C'est le même donc pas de perte du fichier ouvert.

    @+

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 772
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Je sens comme un certain sarcasme dans cette question. Toutefois, mes connaissances limitées sur le fonctionnement de deepcopy et/ou de psycopg2 ne me permettent pas d'en apprécier la substantifique moelle.
    Est ce que tous les objets sont copy-able au sens deepcopy?
    Pourquoi des objets tels que les "sockets" ne sont pas deepcopy-able?

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 100
    Par défaut
    Il n'y a sans doute pas de méthode spéciale __deepcopy__ ou __copy__ sur cette classe (je connais pas psycopg2), la méthode se trouve peut-être

    Bon courage

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 850
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 850
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    L'objet Python est bien copier
    ...
    Mais la référence perdue.
    Avec other.fd = self.fd vous faite juste une copy toute simple de l'objet. C'est le même donc pas de perte du fichier ouvert.

    @+
    C'est un peu ce que je sentais confusément en parlant "d'instance impalpable" que tu as plus justement nommé "référence".
    Merci aussi de m'avoir montré le "is" que je ne connaissais pas

    Citation Envoyé par wiztricks Voir le message
    Est ce que tous les objets sont copy-able au sens deepcopy?
    Pourquoi des objets tels que les "sockets" ne sont pas deepcopy-able?
    En fait le pb n'est pas de savoir si un socket est copiable ou pas mais de la façon dont je voyais le deepcopy. Je pensais que le deepcopy recopiait tous les éléments internes d'un objet. Grosso-modo que l'instruction other.bdd=self.bdd qui fait que ça fonctionne était faite par le deepcopy quoi. Après-tout, ça le fait bien pour des choses simples comme dans cet exemple
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import copy
     
    class cToto(object):
    	def __init__(self, x):
    		print "init"
    		self.var=x
     
    	def __str__(self):
    		return "%s" % repr(self)
     
    	def copy(self):
    		other=copy.deepcopy(self)
    		print "var:", self.var is other.var
    		return other
    # cToto()
     
    a=cToto(5)
    print a, type(a), a.var
     
    b=a.copy()
    print b, type(b), b.var
    Ici b.var vaut 5. Alors pourquoi pas pour des choses comme un fichier ou une connexion bdd ? Et n'oublie pas que si certains ont la chance de pouvoir bosser en équipe et de pouvoir s'élever mutuellement en s'échangeant des infos, d'autres sont seuls à développer et n'ont, pour progresser, que des docs glanées sur le net et les forums. Alors descend de ton Olympe et essaye aussi te mettre un peu à la place des autres...

    Citation Envoyé par fred1599 Voir le message
    Il n'y a sans doute pas de méthode spéciale __deepcopy__ ou __copy__ sur cette classe (je connais pas psycopg2), la méthode se trouve peut-être
    Merci de l'info

    Citation Envoyé par fred1599 Voir le message
    Bon courage
    Merci
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 772
    Par défaut
    Citation Envoyé par Sve@r
    d'autres sont seuls à développer et n'ont, pour progresser, que des docs glanées sur le net et les forums.
    La documentation de copy existe.
    Citation Envoyé par Sve@r
    Alors pourquoi pas pour des choses comme un fichier ou une connexion bdd ?
    Elle mentionne des restrictions plutôt explicites:
    This module does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types. It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.
    Citation Envoyé par Sve@r
    Alors descend de ton Olympe et essaye aussi te mettre un peu à la place des autres...
    Lire la documentation du four micro-onde ou de la machine à laver avant de la mettre en marche fait partie du b.a.ba auquel va s'appliquer tout technicien.
    Pour des fonctionnalités qui relèvent de la programmation, c'est pareil.
    Essayer d'utiliser les "bons outils" dans de "bonnes conditions", quoi de plus normal!
    C'est un des aspects ingrat et barbant du boulot du programmeur.
    Mais difficile de faire l'impasse..

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 100
    Par défaut
    Voilà un exemple de copie d'objet qui me semble fonctionnel

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    from copy import copy
     
    class Mabase(int):
     
        def __init__(self, var):
            self.var = var
        def __copy__(self):
            newone = int.__new__(Mabase, 25)
            newone.__dict__.update(self.__dict__)
            return newone
     
    base = Mabase(45)
    print "base var = %s" %base.var
     
    another_base = copy(base)
    print "another_base var = %s" %another_base.var
     
    another_base.var = 50
    print "another_base var = %s" %another_base.var
     
    print "base var = %s" %base.var
     
    print "type de base : %s" %base.__class__
     
    print "type de another_base : %s" %another_base.__class__
    Résultat

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    base var = 45
    another_base var = 45
    another_base var = 50
    base var = 45
    type de base : <class '__main__.Mabase'>
    type de another_base : <class '__main__.Mabase'>

  10. #10
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Ce n'est sans doute pas pris en charge car il n'y a pas une seule "bonne" façon de traiter ces ressources. Que se passerait-il si l'un des objets décidait de fermer la connexion à la base de donnée et que l'autre continuait à l'utiliser ?

    Il pourrait être plus logique, dans certains cas, d'établir une seconde connexion à la base de données lors d'un deepcopy (ce qui peut être fait en définissant la méthode __deepcopy__).

    Pour une fonction de librairie, c'est plus "safe" de ne rien faire et de laisser le programmeur décider...

  11. #11
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonsoir,

    Citation Envoyé par dividee Voir le message
    Ce n'est sans doute pas pris en charge car il n'y a pas une seule "bonne" façon de traiter ces ressources. Que se passerait-il si l'un des objets décidait de fermer la connexion à la base de donnée et que l'autre continuait à l'utiliser ?
    C'est bien cela le souci. copy.deepcopy "n'initialise pas" les objets "externes". (Edit : class)
    Un objet de type file ou une connexion db ont besoin d’être 'initialiser' (name et optionnellement mode pour le type file).
    Ce qui manque lors d'un copy.deepcopy c'est cela.
    Mais 'initialiser' c'est quoi ? Faire une autre instance.

    Dans l'exemple suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    #
    import copy
     
     
    class cToto(object):
        def __init__(self):
            print "init"
            self.fd = open("/etc/passwd", "r")
     
        def __str__(self):
            return "%s" % repr(self)
     
        def copy(self):
            other = copy.deepcopy(self)
            other.fd = self.fd
            return other
     
    a = cToto()
    b = a.copy()
    print 'a. == b', a == b
    print 'a is b', a is b
    print 'a.fd == b.fd', a.fd == b.fd
    print 'a.fd is b.fd', a.fd is b.fd
    vous voyez bien qu'il y a création de nouveaux objets avec deepcopy alors que = ne fait qu'assigner. Ce n'est pas le but.

    Pour copy.deepcopy on est plus dans du code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    #
    import copy
     
     
    class cToto(object):
        def __init__(self):
            self.args = ("/etc/passwd", "r")
            self.fd = open(*self.args)
     
        def __str__(self):
            return "%s" % repr(self)
     
        def copy(self):
            other = copy.deepcopy(self)
            other.fd = open(*self.args) #  __getinitargs__
            return other
     
    a = cToto()
    b = a.copy()
    print 'a. == b', a == b
    print 'a is b', a is b
    print b.fd.read()
    print 'a.fd', a.fd
    print 'b.fd', b.fd
    Et là voila bien de quoi exploser le code...
    This module does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types.
    Voila qui est sans doute judicieux ,'versatilement' parlant.

    @+

  12. #12
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 850
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 850
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Essayer d'utiliser les "bons outils" dans de "bonnes conditions", quoi de plus normal!
    C'est justement ce que je fais chaque fois que je viens ici...

    Merci du lien vers la doc...


    Citation Envoyé par fred1599 Voir le message
    Voilà un exemple de copie d'objet qui me semble fonctionnel

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    from copy import copy
     
    class Mabase(int):
     
        def __init__(self, var):
            self.var = var
        def __copy__(self):
            newone = int.__new__(Mabase, 25)
            newone.__dict__.update(self.__dict__)
            return newone
     
    base = Mabase(45)
    print "base var = %s" %base.var
     
    another_base = copy(base)
    print "another_base var = %s" %another_base.var
     
    another_base.var = 50
    print "another_base var = %s" %another_base.var
     
    print "base var = %s" %base.var
     
    print "type de base : %s" %base.__class__
     
    print "type de another_base : %s" %another_base.__class__
    Résultat

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    base var = 45
    another_base var = 45
    another_base var = 50
    base var = 45
    type de base : <class '__main__.Mabase'>
    type de another_base : <class '__main__.Mabase'>
    Joli


    Citation Envoyé par dividee Voir le message
    Ce n'est sans doute pas pris en charge car il n'y a pas une seule "bonne" façon de traiter ces ressources. Que se passerait-il si l'un des objets décidait de fermer la connexion à la base de donnée et que l'autre continuait à l'utiliser ?
    Heureusement le cas est déjà prévu. Je sais quel est le père et quel est le fils et seul le père ferme la bdd. Mais c'est bien d'en parler.

    Citation Envoyé par dividee Voir le message
    Il pourrait être plus logique, dans certains cas, d'établir une seconde connexion à la base de données lors d'un deepcopy (ce qui peut être fait en définissant la méthode __deepcopy__).
    C'est d'ailleurs ce qui se passe avec le module sqlite3. Si on reprend mon premier exemple mais qu'on remplace une connexion psycopg2 par une connexion sqlite3, on verra que chaque membre bdd des 2 objets possède une connexion bien distincte.

    J'avais d'ailleurs envisagé cette option au départ mais j'ai dû l'abandonner très vite à cause d'un point crucial: les tables temporaires.
    En effet, mon objet crée des tables temporaires pour travailler. Ces tables sont très pratiques car elles sont automatiquement supprimées lorsque la connexion bdd se ferme. Toutefois j'ai besoin que mes 2 copies accèdent aux données de chacune. Donc chaque copie connait ses tables et les tables de l'autre et ça va super.
    Or, si on crée 2 connexions distinctes, chaque copie ayant sa connexion ne peut plus accéder aux tables de l'autre.

    Citation Envoyé par dividee Voir le message
    Pour une fonction de librairie, c'est plus "safe" de ne rien faire et de laisser le programmeur décider...
    Ouais, ce que je fais en final et à la réflexion je ne m'en porte pas plus mal...

    Citation Envoyé par PauseKawa Voir le message
    Bonsoir,

    C'est bien cela le souci. copy.deepcopy "n'initialise pas" les objets "externes". (Edit : class)
    Un objet de type file ou une connexion db ont besoin d’être 'initialiser' (name et optionnellement mode pour le type file).
    Ce qui manque lors d'un copy.deepcopy c'est cela.
    Mais 'initialiser' c'est quoi ? Faire une autre instance.

    Dans l'exemple suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    #
    import copy
     
     
    class cToto(object):
        def __init__(self):
            print "init"
            self.fd = open("/etc/passwd", "r")
     
        def __str__(self):
            return "%s" % repr(self)
     
        def copy(self):
            other = copy.deepcopy(self)
            other.fd = self.fd
            return other
     
    a = cToto()
    b = a.copy()
    print 'a. == b', a == b
    print 'a is b', a is b
    print 'a.fd == b.fd', a.fd == b.fd
    print 'a.fd is b.fd', a.fd is b.fd
    vous voyez bien qu'il y a création de nouveaux objets avec deepcopy alors que = ne fait qu'assigner. Ce n'est pas le but.

    Pour copy.deepcopy on est plus dans du code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    #
    import copy
     
     
    class cToto(object):
        def __init__(self):
            self.args = ("/etc/passwd", "r")
            self.fd = open(*self.args)
     
        def __str__(self):
            return "%s" % repr(self)
     
        def copy(self):
            other = copy.deepcopy(self)
            other.fd = open(*self.args) #  __getinitargs__
            return other
     
    a = cToto()
    b = a.copy()
    print 'a. == b', a == b
    print 'a is b', a is b
    print b.fd.read()
    print 'a.fd', a.fd
    print 'b.fd', b.fd
    Et là voila bien de quoi exploser le code...
    Ouais. Donc en fait autant me laisser le choix de gérer ma connexion bdd moi-même

    Merci à tous de vos avis éclairés et pertinents (même si certains n'ont pas l'art et la manière de l'exprimer d'une façon aussi polie et aussi agréable à lire que certains autres...)
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  13. #13
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 772
    Par défaut
    La connexion à une BDD est une association entre une entité dans le "client" et d'une autre dans le "serveur".
    C'est une association 1<-->1 "forte" ou chaque entité a des variables d'état "locales" qui traduisent l'état "global" de la connexion.
    De ce fait "copier" la partie "client", sans recréer l'association côté serveur est une opération indéfinie. Ca marche un peu ou pas du tout, de toutes façons, comme çà n'a pas été construit "pour", le résultat n'est pas prédictible.

    Une fois la connexion à la BDD établie, l'application peut (en général) créer autant de curseurs qu'elle souhaite - ils sont associés à la connexion.
    C'est moins lourd qu'une connexion et çà répond aux besoins courants (différents dialogues avec la BDD).

    Plusieurs connexions sont nécessaires lorsqu'on réalise, par exemple, un serveur d'application. La gestion d'un pool de connexions est un exercice intéressant mais lorsque vous avez des bibliothèques telles que SQLAlchemy qui le font pour vous, autant les utiliser.

    Avec sqlite3 serveur et client étant en général dans le même process, cela permet des optimisations qui ne sont pas toujours généralisables.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de copie d'un tableau d'objets
    Par saimer dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 29/04/2015, 16h50
  2. Problème de copie d'une machine à l'autre via SSH
    Par junior222 dans le forum Général Java
    Réponses: 2
    Dernier message: 18/08/2014, 14h26
  3. Problème de copie d'objet
    Par shirya dans le forum VB.NET
    Réponses: 3
    Dernier message: 07/08/2008, 15h43
  4. Réponses: 10
    Dernier message: 25/11/2006, 13h47
  5. Réponses: 15
    Dernier message: 23/06/2006, 13h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo