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 :

Souci de déclaration de fonction


Sujet :

Python

  1. #1
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut Souci de déclaration de fonction
    Bonjour à tous,

    Je suis devant un petit problème que je ne parviens pas à résoudre. J'ai codé un petit serveur, qui attend des connexions ainsi que certains paquets précis pour effectuer certaines tâches.

    Mais, plutôt que d'écrire un paquet d'instructions, j'ai décidé de structurer un peu le script en créant plusieurs fonctions.

    Voici un bout de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def initialisation_serveur():
         # Je crée le socket
         le_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         [...]
         # Puis je mets le serveur en écoute :
         made_connexion, infos_connexion = le_socket.accept()
     
         # J'appelle enfin une autre fonction précédemment définie pour réceptionner les paquets :
         reception();
    Ensuite, dans reception():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    def reception():
         [...]
         msg_recu = made_connexion.recv(1024)
    Donc, cette ligne fonctionne logiquement si je la place dans initialisation_serveur(), mais elle ne fonctionne logiquement pas tel que je l'ai écrite - dans reception() - : je comprends pourquoi, made_connexion n'est pas définie dans reception()...mais je ne parviens pas à trouver comment résoudre le problème ; je pourrais tout mettre dans la même fonction, mais au final ça risque de faire très bordélique.

    Quelqu'un aurait une suggestion ?

    D'avance, merci'

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    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 715
    Par défaut
    Salut,

    Citation Envoyé par .....1..... Voir le message
    initialisation_serveur(), mais elle ne fonctionne logiquement pas tel que je l'ai écrite - dans reception() - : je comprends pourquoi, made_connexion n'est pas définie dans reception()...mais je ne parviens pas à trouver comment résoudre le problème
    Dans les tutos, il y a des chapitres entiers sur les fonctions, les paramètres, la portée des variables... Et de quoi s'entraîner avec des exercices (corrigés).


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

  3. #3
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut
    Salut,

    Merci pour ta réponse. Déjà mon titre est trompeur, je n'ai pas de souci avec une fonction mais plutôt avec une variable...désolé pour l'erreur.

    Alors à force de lire et relire des trucs, j'ai fini par déclarer made_connexion() en tant que global avant de faire mon made_connexion, infos_connexion... et ça fonctionne.

    Je ne pensais pas que je pouvais déclarer une global directement au sein d'une fonction.

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    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 715
    Par défaut
    Citation Envoyé par .....1..... Voir le message
    Je ne pensais pas que je pouvais déclarer une global directement au sein d'une fonction.
    Maintenant que vous avez une façon de le faire, essayez d'en trouver une autre (sans utiliser global).

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

  5. #5
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut
    Re,

    Présentement je suis parti sur la résolution d'un autre problème

    Vous auriez une piste concernant une autre solution ? Car personnellement je trouve effectivement assez bizarre de déclarer une global dans une fonction...

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par .....1..... Voir le message
    Car personnellement je trouve effectivement assez bizarre de déclarer une global dans une fonction...
    Il faut lire les docs. Une variable créée en dehors de toute fonction est connue dans toutes les fonctions écrites après. Ex
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> a=123
    >>> def toto(): print(a)
    >>> toto()
    123
    Mais la variable n'est accessible qu'en lecture seule (ce qui est déjà une protection de base car un des principaux soucis des globales est leurs modifications potentiellement non suivies). Si toutefois tu veux quand-même pouvoir modifier la variable dans la fonction, tu dois alors l'indiquer explicitement. Et la syntaxe pour ça est le mot clef "global" suivi de la variable à autoriser la modif.

    Citation Envoyé par .....1..... Voir le message
    Vous auriez une piste concernant une autre solution ?
    Sans déconner, tu viens du forum C où tu as écrit une fonction de Fibonacci, laquelle reçoit en paramètre l'indice que la fonction doit calculer. Et tu ne te dis pas qu'en Python c'est la même chose ? Si tu veux qu'une fonction puisse recevoir une valeur venue de l'extérieur, tu définis pour la fonction un paramètre lequel contiendra alors ladite valeur !!!
    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]

  7. #7
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut
    Salut,

    Relax mon jeune ami, relax. Il n'y a pas de question bête, comme le disent souvent les enseignants

    Justement, j'ai fait ce que tu viens de m'indiquer : ça rend le code bien plus compliqué, ceci dit ça me semble plus propre et cohérent comparer au fait d'avoir un vieux global au milieu de nul part. Le truc c'est que j'ai eu des cours de Java il y a un moment, et le prof n'arrêtait pas de me dire "vous faites du Java, oubliez le C, ici on programme en Java, donc on programme Orienté Objet". Du coup ça va sembler idiot mais j'essayais de ne pas appliquer ce que tu as décrit juste au-dessus car il s'agit de Python et non de C

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par .....1..... Voir le message
    Il n'y a pas de question bête, comme le disent souvent les enseignants
    Je ne t'ai pas attaqué sur ta question, mais sur le fait que tu n'as pas utilisé des connaissances que je te sais connaitre pour trouver la réponse tout seul.

    Citation Envoyé par .....1..... Voir le message
    Justement, j'ai fait ce que tu viens de m'indiquer : ça rend le code bien plus compliqué
    Là j'ai un gros doute. Parce qu'entre
    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
    def reception():
    	[...]
    	msg_recu = made_connexion.recv(1024)
    	[...]
    # reception()
     
    def initialisation_serveur():
    	# Je crée le socket
    	le_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    	[...]
    	# Puis je mets le serveur en écoute :
    	made_connexion, infos_connexion = le_socket.accept()
     
    	# J'appelle enfin une autre fonction précédemment définie pour réceptionner les paquets :
    	reception()
    # initialisation_serveur()

    et

    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
    def reception(conn):
    	[...]
    	msg_recu = conn.recv(1024)
    	[...]
    # reception()
     
    def initialisation_serveur():
    	# Je crée le socket
    	le_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    	[...]
    	# Puis je mets le serveur en écoute :
    	made_connexion, infos_connexion = le_socket.accept()
     
    	# J'appelle enfin une autre fonction précédemment définie pour réceptionner les paquets :
    	reception(made_connexion)
    # initialisation_serveur()
    j'ai du mal à voir en quoi le second code est "bien plus compliqué" que le premier.

    Citation Envoyé par .....1..... Voir le message
    Le truc c'est que j'ai eu des cours de Java il y a un moment, et le prof n'arrêtait pas de me dire "vous faites du Java, oubliez le C, ici on programme en Java, donc on programme Orienté Objet".
    Je veux bien admettre (non, j'admets en réalité parfaitement) que Java sera plus compétent pour faire de la POO que le C. Toutefois il est possible de faire en C ce que je nomme la "presque POO" (des structures bien établies et des fonctions dédiées à manipuler ces structures uniquement). Mais même sans ça, demander "d'oublier" le C !!!!! Ce n'est pas parce qu'on fait de la POO que les bases changent. Même en POO on continue quand-même à échanger des valeurs entre les fonctions !!!

    Citation Envoyé par .....1..... Voir le message
    car il s'agit de Python et non de C
    Ok. Il n'y a pas de question bête, mais il y a des idées bêtes. Et là c'est une sacrée bêtise. Enfin mieux vaut que ce soit maintenant qu'elle sorte qu'après 3 ans de prog et d'habitude déjà ancrées. Comme je l'ai dit, la POO ne renie pas les bases, au contraire elle les utilise et les enrichit.

    Imagine que tu doives travailler sur des carrés et des cercles en C. Ok, tu crées tes structures t_carre et t_cercle. Puis tu dois définir une fonction pour l'afficher à une position X/Y. Déjà là tu seras bloqué par les noms et tu devras alors définir une fonction "afficheCarre" et une autre "afficheCercle".

    Puis tu crées ton carré (t_carre carre) mais tu dois appeler son affichage ainsi: afficheCarre(&carre, X, Y) tout en risquant un jour de te tromper et d'appeler afficheCarre(&cercle, X, Y) et obtenir n'importe quoi. Mais bon, malgré ces soucis, on s'en sort quand-même parce qu'en C on n'a rien d'autre donc on fait avec (et on est déjà content d'avoir les structures qui permettent la programmation "structurée").

    Arrive la POO. Est-ce que cela va changer les bases ? Pas du tout. Tu définis un objet (classe) "cCarre", un autre "cCercle".
    Sauf que là tu as accès à d'autres outils. Par exemple de là tu pourras y intégrer pour chacun une méthode (fonction interne) nommée bêtement "affiche" sans que tu te fasses chier à chercher un nom plus intelligent et sans que l'homonymie ne gêne l'interpréteur.

    Puis pour l'utilisation, tu crées ton objet "carre" (carre=cCarre()) et ton autre objet "cercle" (cercle=cCercle()). Ensuite, pour afficher le carré te suffit d'appeler carre.affiche(X, Y), et pour afficher le cercle tu appelles cercle.affiche(X, Y) et automatiquement c'est la bonne fonction qui sera appelée pour chaque objet. Pas de risque de se tromper. C'est ça la POO: pouvoir attribuer des actions directement aux objets pour se simplifier les choses. Mais même en POO tu dois toujours passer à la fonction des éléments (éléments ne faisant pas partie de l'objet sinon la fonction y a accès) lui permettant d'orienter son travail (ici X et Y).

    Dommage, ton prof devait être très compétent en Java... mais s'il a tenté de te faire perdre les racines de la prog je pense qu'il a raté un truc.
    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]

  9. #9
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut
    Salut !

    Comme j'ai plusieurs fonctions, ça le rend le code un chouïa plus fourni, mais en effet ce n'est pas beaucoup plus compliqué pour autant.

    Citation Envoyé par Sve@r Voir le message
    Ok. Il n'y a pas de question bête, mais il y a des idées bêtes. Et là c'est une sacrée bêtise. Enfin mieux vaut que ce soit maintenant qu'elle sorte qu'après 3 ans de prog et d'habitude déjà ancrées.
    Entièrement d'accord

    Au top tes explications C'est marrant mais personne encore avant ne m'avait fait un comparatif de la sorte : en fait c'est dommage car mine de rien je viens de piger quelque chose concernant la différence entre POO et "programmation classique" alors que ça va faire un an que je m'intéresse à la programmation.

    Il était compétent en effet, mais pas très pédagogique. Ayant au moment où j'ai commencé son cours j'avais quelques bases en programmation, donc un peu de recul, ce qui m'a permis de me dire que sa façon d'enseigner n'était pas très efficace...enfin voilà, à cause de lui je faisais tout pour ne pas reproduire en POO ce que je pouvais faire en C puisque sinon j'avais le droit à des remarques...

    Si toutefois tu repasses, je bloque sur un problème depuis un moment : j'ai mon serveur qui utilise le module socket, et je souhaite communiquer avec un client. Ce que j'aimerais, c'est que lorsque je fais $ python3 client.py, le script se lance, puis :
    • le client initialise la connexion au serveur - qui tourne déjà -.
    • le client attend qu'on lui passe des commandes avant de les traiter et de les envoyer au serveur - ou de nous retourner un message, comme de l'aide -.
    • le client récupère les éventuelles réponses et les affiche sur l'interface.


    Un peu comme si j'utilisais MSN, en fait (on lance MSN puis on échange ensuite des messages avec quelqu'un). Malheureusement j'ai déjà essayé asyncio et argparse, mais sans succès (en fait je ne suis même pas certain d'être sur la bonne voie)...tu aurais une suggestion ? Je sèche complètement (j'ai cherché "CLI python", mais pareil, je ne suis pas sûr d'être sur la bonne voie).

  10. #10
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par .....1..... Voir le message
    Si toutefois tu repasses, je bloque sur un problème depuis un moment : j'ai mon serveur qui utilise le module socket, et je souhaite communiquer avec un client. Ce que j'aimerais, c'est que lorsque je fais $ python3 client.py, le script se lance, puis :
    • le client initialise la connexion au serveur - qui tourne déjà -.
    • le client attend qu'on lui passe des commandes avant de les traiter et de les envoyer au serveur - ou de nous retourner un message, comme de l'aide -.
    • le client récupère les éventuelles réponses et les affiche sur l'interface.


    Un peu comme si j'utilisais MSN, en fait (on lance MSN puis on échange ensuite des messages avec quelqu'un). Malheureusement j'ai déjà essayé asyncio et argparse, mais sans succès (en fait je ne suis même pas certain d'être sur la bonne voie)...tu aurais une suggestion ? Je sèche complètement (j'ai cherché "CLI python", mais pareil, je ne suis pas sûr d'être sur la bonne voie).
    Ben argparse c'est pour analyser des arguments passés au programme, et asyncio c'est de l'IO asynchrone. Ces deux outils peuvent t'aider. argparse pour décortiquer ta commande et asyncio pour tout ce qui est communication TCP/IP. Mais peut-être que ces outils sont trop évolués par rapport à ton besoin...
    Dans ton discours tu as employé le terme "client" et "interface". Est-ce que ce sont deux entités distinctes (le client qui dialogue avec le serveur et avec l'interface) ou bien la même (l'interface est donc le client qui va parler au serveur et récupérer ses retours) ???
    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]

  11. #11
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut
    Re,

    Merci pour ta réponse.

    Pour argparse et asynchio, c'est effectivement ce que j'ai fini pas plus ou moins comprendre, mais comme je suis tombé dessus en recherchant comment faire ce que je voulais faire, j'ai quand-même potassé les modules histoire de voir où ça allait me mener.

    L'idée, c'est que j'ai serveur.py qui tourne, et quand je lance client.py, celui-ci initialise une connexion au serveur (pour le moment en local), et attend ensuite que je lui envoie une commande. Par exemple :
    • Si je fais : send msg --> le msg est envoyé au serveur.
    • Si le serveur me répond 'msg reçu', la réponse s'affiche instantanément sous mes yeux - sans que j'ai besoin de faire socket_client.recv(xx) -.
    • Si je génère une erreur dans mon message - par exemple en envoyant èèééôâi¨ï - la réponse du serveur indiquant l'erreur s'affichera de la même façon instantanément - du genre "Erreur d'encodage" qui pop sans que j'ai à faire socket_client.recv(xx) -.


    Dans mon idée, le client fait aussi office d'interface (donc quand je le lance, il se connecte au serveur puis attend que je lui passe des commandes). Après je ne sais pas ce qui est le mieux...

    j'espère que c'est assez clair

  12. #12
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par .....1..... Voir le message
    Dans mon idée, le client fait aussi office d'interface (donc quand je le lance, il se connecte au serveur puis attend que je lui passe des commandes). Après je ne sais pas ce qui est le mieux...
    Ok. C'est effectivement le mieux. Le client c'est juste une interface et il envoie ses requêtes au serveur et attend sa réponse. J'avais peur que le client soit un truc externe auquel se connecte l'interface. Dans ce cas, le client aurait en fait été serveur intermédiaire et bon ça aurait été évidemment plus chiant (si t'as 2 prog qui communiquent t'as 2 problèmes potentiels, si t'en as 3 qui communiquent alors t'as 6 problèmes potentiels).


    Citation Envoyé par .....1..... Voir le message
    Si le serveur me répond 'msg reçu', la réponse s'affiche instantanément sous mes yeux - sans que j'ai besoin de faire socket_client.recv(xx) -.
    Si je génère une erreur dans mon message - par exemple en envoyant èèééôâi¨ï - la réponse du serveur indiquant l'erreur s'affichera de la même façon instantanément - du genre "Erreur d'encodage" qui pop sans que j'ai à faire socket_client.recv(xx) -.
    Suis désolé, ça ce n'est pas possible. Sur Unix/Linux les différents programmes sont toujours totalement isolés dans leur bulle d'exécution et ne s'interfèrent pas. Si le serveur doit dire un truc, ce truc ne pourra pas s'afficher sur le client sans qu'il ne le récupère au préalable
    Ensuite les façons de le récupérer peuvent là utiliser plusieurs technos selon les cas. Si c'est sur des machines distinctes alors la seule façon c'est une communication TCP/IP. Ensuite si c'est sur la même machine là t'as d'autres outils comme les pipes, les sockets, les files de message et la mémoire partagée (et bien entendu toujours possible TCP/IP aussi).
    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
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut
    Re,

    merci pour ta réponse encore une fois.

    Alors je me suis mal exprimé : par exemple, pour le_socket.recv(1024), je voulais dire qu'une fois le script client lancé, on a pas besoin de l'écrire nous même (pas comme si on venait d'ouvrir l'interpréteur par exemple) : la ligne de code figure bien dans le script, mais l'utilisateur qui passe par le client n'a pas à écrire lui-même tout ça ; exemple :
    • Je lance le script client.py - serveur.py tourne déjà -.
    • Le script initialise la connexion puis attend quelque chose.
    • J'écris alors "send nom patient 1", puis je valide par entrée.
    • Là, le programme envoie le paquet au serveur, qui répond, puis le client réceptionne la réponse.
    • Et devant moi, sans que je n'ai rien à faire, la réponse s'affiche : "Marc Bidule".


    En fait, ce que je ne vois pas, c'est comment :
    • Ecrire le script pour qu'il effectue les connexions, puis attende enfin une commande de l'utilisateur.
    • Traite les commandes de l'utilisateur (envoi d'un paquet, fermeture du client...) et agisse en conséquence : affichage de la réponse du serveur, fermeture...


    Quand je me relis, je ne me trouve pas très clair, je vais essayer de montrer un exemple :
    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
    import socket
    import argparse # par exemple
     
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect(('localhost', 12000))
     
    # On entre ensuite dans une fonction qui va attendre une saisie de l'utilisateur et la traiter. Admettons que l'utilisateur fasse un ' envoyer nom patient 1 '
    # On entrera dans une autre fonction qui fera :
    client_connect.send(b"nom patient 1")
    response = client_connect.recv(1024)
    print("Le nom du patient {0} est : {1}".format(nombre, response.decode()) #on suppose que nombre a aussi été attribué en fonction de la commande, donc qu'il vaudra ici 1
     
    # Si l'utilisateur fait par exemple ' stop ', on entre alors dans une fonction qui fait :
    client_connect.close()
    exit(1)
    Je ne sais pas si c'est très clair...en fait voilà : je ne vois pas comment je peux mettre le script en pause en attente d'une commande de la part de l'utilisateur.

  14. #14
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut
    Re,

    J'ai trouvé une solution : je vais utiliser argparse ou sys afin de lancer le client avec un paramètre, et de lui faire faire ce que je veux en fonction dudit paramètre. Exemple :

    $ python3 client.py envoyer nom_patient_1

    Donc le client se fermera à chaque fois. Le seul bémol, c'est que si je fais un socket_client.close(), le serveur s’interrompt aussi.

  15. #15
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 715
    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 715
    Par défaut
    Salut,

    Citation Envoyé par .....1..... Voir le message
    Donc le client se fermera à chaque fois. Le seul bémol, c'est que si je fais un socket_client.close(), le serveur s’interrompt aussi.
    Il faut écrire un serveur qui soit capable de gérer plus d'une connexion client et définir un protocole d'échange de messages entre clients et serveur ou utiliser un protocole existant (HTTP par exemple).

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

  16. #16
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par .....1..... Voir le message
    Le seul bémol, c'est que si je fais un socket_client.close(), le serveur s’interrompt aussi.
    Je ne connais pas assez bien les outils Python. Mais ce genre de truc je l'ai déjà fait en C.
    Il faut que ton serveur, quand il voit arriver un client, lance un fork() (commande disponible sur Unix seulement, pas Windows). Cela génère un fils identique au père (toutes les variables connues quand le fils est généré sont alors dupliquées et connues du fils donc y compris les sockets ouvertes).
    De là, le fils prend en charge le client tandis que le père se remet en écoute. Et quand le fils se termine, il peut quitter sans que le père en soit gêné.

    ici un cours sur les sockets en C avec un exemple complet de client/serveur qui fait exactement ce que tu dis (différents clients se connectent au serveur et peuvent lui envoyer des infos et le serveur ne quitte jamais). Malheureusement écrit en C donc à réécrire en Python (peut-être que je le ferai pour m'amuser)

    Et ici un mini-exemple de fork (qui existe en Python) pour te montrer le principe
    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
    #!/usr/bin/env python3
    # coding: utf-8
     
    import os
    pid=os.fork()
    if pid == 0:
    	print("Je suis le fils %d" % os.getpid())
    	# exit(0)			# A décommenter ppur arrêter le fils
    else:
    	print("Je suis le père %d et mon fils est %d" % (os.getpid(), pid))
    # if
     
    # Ce n'est pas parce qu'on a quitté le "if" que le fils s'arrête (sauf si on décommente le "exit(0)" du fils)
    print("Attention, ici 2 processus tournent en parallèle (%d)" % os.getpid())

    Sinon il y a les thread, qui sont plus tardives mais qui fonctionnent sur Unix et Windows. Donc à privilégier si tu veux faire un serveur pouvant fonctionner en multi-os. Mais d'une part là ça dépasse mes connaissances Python et d'autre part le principe des thread n'est pas le même que celui des fork car il n'ya pas indpendance des zones mémoires (tu peux taper "différences fork thread" sur un moteur de recherche). ici un tuto Python client/serveur basé sur les thread. Sauf qu'il est pour P2 et que j'ai pas réussi à le porter sous P3.
    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]

  17. #17
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut
    Salut,

    Merci pour vos réponses !!

    Je suis parti sur la solution proposée par wiztricks, malheureusement je ne m'en sors pas : dès lors que l'un des clients interrompt la connexion, le serveur se ferme, je ne comprends pas pourquoi, même après un try/except. Pourtant mon serveur reçoit correctement des messages de divers clients. Donc je vais potasser ça.

    Sinon je testerai la méthode du fork(), malheureusement même en C j'ai toujours eu du mal avec cette fonction

    Cependant, ma deadline étant aujourd'hui, je préfère rendre un truc correct mais sur lequel il y a un problème en expliquant le problème et comment je pourrais le résoudre plutôt que de rendre en retard un truc tout mal foutu que j'aurais essayé de rattraper à la va-vite et qui ne fonctionnerait pas plus pour autant.

    Quitte à reprendre ça un peu plus tard pour l'améliorer en corrigeant le dit problème

  18. #18
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par .....1..... Voir le message
    Sinon je testerai la méthode du fork(), malheureusement même en C j'ai toujours eu du mal avec cette fonction
    Va sur le fofo C (ou le fofo Linux), je te l'expliquerai.

    Citation Envoyé par .....1..... Voir le message
    Cependant, ma deadline étant aujourd'hui, je préfère rendre un truc correct mais sur lequel il y a un problème en expliquant le problème et comment je pourrais le résoudre plutôt que de rendre en retard un truc tout mal foutu que j'aurais essayé de rattraper à la va-vite et qui ne fonctionnerait pas plus pour autant.

    Quitte à reprendre ça un peu plus tard pour l'améliorer en corrigeant le dit problème
    Désolé. De mon côté j'ai porté l'exemple simpliste client/serveur C dont je t'ai parlé sous Python. En fait ça a été plus facile que ce que je croyais. Et le gain !!! 236 lignes C contre 42 Python pour le serveur, et 141 lignes C contre 28 Python pour le client.
    Et ça fonctionne (enfin le client fait juste saisir une chaine qu'il envoie au serveur). Mais quand le client termine, le serveur, lui, continue pour un autre client. Et le serveur peut aussi gérer plusieurs clients en parallèles.

    Code du serveur
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #!/usr/bin/env python3
    # coding: utf-8
     
    import socket
    import sys
    import os
     
    class cSocket(object):
    	def __init__(self, port, host="localhost"):
    		self.__connect=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    		self.__connect.bind((host, port))
    		self.__dialog=None
    		print("socket %s prête à écouter sur le port %d" % (self.__connect, port))
    	# __init__()
     
    	# Ecoute
    	def listen(self):
    		self.__connect.listen(1)
    		while True:
    			(self.__dialog, infos)=self.__connect.accept()
    			pid=os.fork()
    			if pid == 0:
    				self.__fils()
    				exit(0)
    			# if
    		# while
    	# listen()
     
    	# Gestion du fils qui va récupérer les messages du client
    	def __fils(self):
    		while True:
    			msg=self.__dialog.recv(1024).decode("utf-8")
    			print("client %d: Message: [%s]" % (os.getpid(), msg))
    			if msg == "EOT":
    				print("client %d: EOT" % os.getpid())
    				break
    			# if
    		# while
    	# __fils()
    # class cSocket
     
    if __name__ == "__main__":
    	sock=cSocket(int(sys.argv[1]))
    	sock.listen()
    # if

    Et le client
    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 python3
    # coding: utf-8
     
    import socket
    import sys
     
    class cSocket(object):
    	def __init__(self, port, host="localhost"):
    		self.__dialog=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    		self.__dialog.connect((host, port))
    		print("socket %s connectée avec %s sur le port %d" % (self.__dialog, host, port))
    	# __init__()
     
    	def dialogue(self):
    		while True:
    			msg=input("Tapez votre message (EOT pour quitter): ")
    			self.__dialog.send(msg.encode("utf-8"))
    			if msg == "EOT":
    				print("Client teminé")
    				break
    			# if
    		# while
    	# dialogue()
    # class cSocket
     
    if __name__ == "__main__":
    	sock=cSocket(int(sys.argv[1])).dialogue()
    # if

    Il faut les appeler en leur passant en paramètre le port à utiliser.
    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]

  19. #19
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Va sur le fofo C (ou le fofo Linux), je te l'expliquerai.
    Ça marche, à l'occasion je passerai.


    Citation Envoyé par Sve@r Voir le message
    Désolé. De mon côté j'ai porté l'exemple simpliste client/serveur C dont je t'ai parlé sous Python. En fait ça a été plus facile que ce que je croyais. Et le gain !!! 236 lignes C contre 42 Python pour le serveur, et 141 lignes C contre 28 Python pour le client.
    Mais c'est excellent !! Moi je galère depuis plusieurs jours là-dessus et toi en une après-midi tu fais ce que j'ai fait en carrément mieux

    Mais curieusement la syntaxe est bien différente de la mienne...pourquoi tu utilises self.__xx ? Sinon le shebang (#!/usr/bin/env python3) il sert à quoi ? J'ai lu que c'était pour indiquer au système où chercher python3, mais en l'enlevant ça fonctionne sans problème...

    Sinon c'est pas bête l'idée de demander à l'utilisateur de passer ne paramètre le port d'écoute/de connexion. Si ça ne te dérange pas je te la pique volontiers

    Plus qu'à essayer de comprendre ce que tu as fait afin de comprendre ce qui ne passe pas chez moi.

    En fait, je ne comprends pas bien le self : ce que je trouve étrange c'est que tu définis __fils() comme devant être appelée avec self, mais tu l'appelles de cette façon : self.__fils() : cette syntaxe est une façon de passer self à __fils ?

    Re : merci pour ton exemple en tout cas, ça m'a permis de comprendre comment bien utiliser le fork() : moi je le mettais au mauvais endroit Bon ceci dit le fonctionnement de mon serveur n'est pas encore optimal pour autant...

    Re-re : finalement, je n'ai pas dû bien saisir : le serveur me génère des erreurs à chaque fois que le client se ferme, mais même s'il continue de tourner, le script semble s'être arrêté (j'ai une variable qui prend certaines valeurs, et je perds ces valeurs chaque fois que le script stoppe, ce qui semble être le cas).

  20. #20
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2018
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2018
    Messages : 64
    Par défaut
    Salut

    Alors là j'ai fait fort : en essayant de corriger mon script, je me retrouve avec la comportement attendu...sauf que du coup quand je suis le fil d'exécution à partir du code (break, return, les appels, etc...) je ne comprends pas du tout ce qu'il se passe, ni pourquoi ça fonctionne

    Bon, par contre, ma variable globale est encore réinitialisée malgré le fait que le script reste lancé...

    Bon, je commence à mieux comprendre ce qu'il se passe : déjà je croyais que sys.exit() demandait la fermeture du script, mais visiblement c'est pas le cas. Sinon, je me demandais : la variable global var_glo est initialisée par le Père --> Mais si le fils cherche à en récupérer le contenu, sera-t'elle réinitialisée ? La question parait peut-être idiote mais j'ai l'impression que la seule réponse vient de là...

    Edit : ma question ne semblait finalement pas si bête : https://stackoverflow.com/questions/...riables-shared

Discussions similaires

  1. Déclaration de fonction dans le "main".
    Par Pragmateek dans le forum C++
    Réponses: 14
    Dernier message: 23/06/2006, 19h32
  2. déclaration de fonctions externes
    Par poukill dans le forum C++
    Réponses: 40
    Dernier message: 17/05/2006, 16h15
  3. Réponses: 4
    Dernier message: 11/05/2006, 15h34
  4. Réponses: 6
    Dernier message: 20/11/2005, 02h53
  5. [JS] Problème déclaration de fonction
    Par glloq8 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 23/09/2005, 10h22

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