La fonction input avec un fichier txt ou csv

Fermé
LALO_5656 Messages postés 29 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 21 septembre 2024 - Modifié le 24 janv. 2023 à 16:10
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 - 24 janv. 2023 à 16:32

Bonjour à tous,

Mon code génère plusieurs points à partir d'une source de 4 points dans une emprise définie et me récupère les coordonnées x,y dans un fichier CSV.
Je voudrais généraliser ce code en demandant avec la fonction input les paramètres du programme, à savoir :

  • les 4 coordonnées sources
  • l'emprise du projet (x,y) et (A,B).

Pour le moment, les 4 coordonnées sources sont dans un fichier texte et l'emprise du projet est dans un fichier texte.

Voila le code :

import matplotlib.pyplot


def equdroite(x0, y0, x1, y1):
    a = y1 - y0
    b = x0 - x1
    c = -(b * y0 + a * x0)
    #     print("verif00:",sign(x0,y0,a,b,c),sign(x1,y1,a,b,c))
    return a, b, c


def inside(Poly, p):
    for P in Poly:
        a, b, c, s, x, y = P[0], P[1], P[2], P[3], pp[0], pp[1]
        if s * sign(x, y, a, b, c) < 0:
            #             print("outside:",a,b,c,s,x,y)
            return False
    return True


def sign(x, y, a, b, c):
    return a * x + b * y + c


# Les 4 coordonnées sources
(x, y) = ([325010, 325015, 325015, 325010], [2077560, 2077560, 2077555, 2077555])
# x = [325010, 325015, 325015, 325010, 325010]
# y = [2077560, 2077560, 2077555, 2077555, 2077560]
sg = 5
# L'emprise du projet
(A, B) = ([324989.345, 324987.133, 324987.502, 325037.452, 325035.977, 324989.345],
          [2077586.246, 2077553.622, 2077537.955, 2077537.402, 2077589.933, 2077586.246])
# A = [324989.345,  324987.133,  324980,  325037.452,  325035.977,  324989.345]
# B = [2077586.246, 2077553.622, 2077800, 2077537.402, 2077589.933, 2077586.246]
# avgA,avgB=sum(A)/len(A),sum(B)/len(B)
# # print ("avg:",avgA,avgB)
# A=[x-avgA for x in A]
# B=[x-avgB for x in B]
# x=[x-avgA for x in x]
# y=[x-avgB for x in y]
nc = len(A) - 1
E = []
for p0 in range(nc):
    p1 = (p0 + 1) % nc
    p2 = (p0 + int(nc / 2)) % nc
    a, b, c = equdroite(A[p0], B[p0], A[p1], B[p1])
    s = sign(A[p2], B[p2], a, b, c)
    #     print("inloop:",p0,a,b,c,s)
    E.append([a, b, c, s, p0, p1])
# print("E:",E)
for p in range(nc):
    for C in E:
        if p != C[4] and p != C[5]:
            a, b, c, s, xp, yp = C[0], C[1], C[2], C[3], A[p], B[p]
            v = sign(xp, yp, a, b, c)
            if s * v < 0:
                #             print("outside:",a,b,c,s,xp,yp)
                print("OUPS!", s, v)
matplotlib.pyplot.plot(A, B)
matplotlib.pyplot.scatter(x, y, color="r")
matplotlib.pyplot.axis("equal")
matplotlib.pyplot.grid()

phg = (int(min(A) / sg) * sg, int(min(B) / sg) * sg)
pbd = (int(max(A) / sg + 1) * sg, int(max(B) / sg + 1) * sg)
nrow = int((pbd[0] - phg[0]) / sg) + 1
ncol = int((pbd[1] - phg[1]) / sg) + 1
# print(phg)
# print(nrow,ncol)
prouge = []
for row in range(nrow):
    for col in range(ncol):
        pp = (phg[0] + sg * row, phg[1] + sg * col)
        if inside(E, pp):
            prouge.append(pp)
xrouge = [ppp[0] for ppp in prouge]
yrouge = [ppp[1] for ppp in prouge]
matplotlib.pyplot.scatter(xrouge, yrouge, color="g")
matplotlib.pyplot.scatter(x, y, color="r")
with open("coordout.csv", "w") as f:
    print("X;Y", file=f)
    for xrouge, yrouge in prouge:
        print(f"{xrouge};{yrouge}", file=f)

matplotlib.pyplot.show()

D'avance merci

A voir également:

13 réponses

mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
20 janv. 2023 à 13:31

Bonjour

A priori le code devrait ressembler à ceci :

from tkinter import filedialog

def prompt_filename(title="Sélectionner le fichier source"):
    return filedialog.askopenfilename(
        initialdir="/", title="Sélectionner le fichier source",
        filetypes=(
            ("Fichier texte", "*.txt"),
            ("Fichier csv", "*.csv")
        )
    )

def read_coords(f_coords):
    coords = list()
    for line in f_coords:
        print(line.strip())
        # ...
    return coords

def read_emprise(f_emprise):
    emprise = ...
    for line in f_emprise:
        print(line.strip())
        # ...
    return emprise

filename_coords = prompt_filename("Sélectionner le fichier de coordonnées")
with open(filename_coords, "r") as f_coords:
    coords = read_coords(f_coords)

filename_emprise = prompt_filename("Sélectionner le fichier de l'emprise")
with open(filename_emprise, "r") as f_coords:
    coords = read_emprise(f_coords)

# ...

Bonne chance

1
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 Ambassadeur 1 557
17 janv. 2023 à 09:19

bonjour, tu te demandes comment lire des données dans un fichier?

0
LALO_5656 Messages postés 29 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 21 septembre 2024 2
Modifié le 20 janv. 2023 à 12:44

Bonjour yb_be c'est à peu près cela. J'aimerais, en exécutant le code, voir la fonction input qui me demande de saisir le fichier du fichier texte contenant les 4 coordonnées, ainsi que celui de l'emprise du projet, puis qu'il continue l'exécution du code.

Merci

0
LALO_5656 Messages postés 29 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 21 septembre 2024 2
17 janv. 2023 à 12:23

 Bonjour voila le code que je voudrais inserer cependant j'arrive pas bien faire.

Ou c'est pas la bonne methode , je suis perdu 

# Les 4 coordonnées sources
filename = filedialog.askopenfilename(initialdir="/", title="selectionner le fichier source",
                                      filetypes=(("fichier texte", "*.txt"), ("fichier csv", "*.csv")))

(x, y) = filename
# x = [325010, 325015, 325015, 325010, 325010]
# y = [2077560, 2077560, 2077555, 2077555, 2077560]
sg = 5
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557
17 janv. 2023 à 12:28

Il manque pas un import dans ton code?  Il est complet?

As-tu déjà fait un essai de lecture d'un fichier, avec un nom de fichier mis en dur dans le code?

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
LALO_5656 Messages postés 29 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 21 septembre 2024 2
Modifié le 20 janv. 2023 à 12:43

Tous les import sont faits et je pense que le code est complet.

Quand j'ajoute la fonction os.popen(filename) le fichier s'ouvre .

Je reçois l'erreur:

TypeError: read expected 2 arguments, got 1

Le code complet:

import os
from tkinter import filedialog

import matplotlib.pyplot


def equdroite(x0, y0, x1, y1):
    a = y1 - y0
    b = x0 - x1
    c = -(b * y0 + a * x0)
    #     print("verif00:",sign(x0,y0,a,b,c),sign(x1,y1,a,b,c))
    return a, b, c


def inside(Poly, p):
    for P in Poly:
        a, b, c, s, x, y = P[0], P[1], P[2], P[3], pp[0], pp[1]
        if s * sign(x, y, a, b, c) < 0:
            #             print("outside:",a,b,c,s,x,y)
            return False
    return True


def sign(x, y, a, b, c):
    return a * x + b * y + c


# Les 4 coordonnées sources
filename = filedialog.askopenfilename(initialdir="/", title="selectionner le fichier source",
                                      filetypes=(("fichier texte", "*.txt"), ("fichier csv", "*.csv")))

(x, y) = filename
# x = [325010, 325015, 325015, 325010, 325010]
# y = [2077560, 2077560, 2077555, 2077555, 2077560]
sg = 5
# L'emprise du projet
(A, B) = ([324989.345, 324987.133, 324987.502, 325037.452, 325035.977, 324989.345],
          [2077586.246, 2077553.622, 2077537.955, 2077537.402, 2077589.933, 2077586.246])
# A = [324989.345,  324987.133,  324980,  325037.452,  325035.977,  324989.345]
# B = [2077586.246, 2077553.622, 2077800, 2077537.402, 2077589.933, 2077586.246]
# avgA,avgB=sum(A)/len(A),sum(B)/len(B)
# # print ("avg:",avgA,avgB)
# A=[x-avgA for x in A]
# B=[x-avgB for x in B]
# x=[x-avgA for x in x]
# y=[x-avgB for x in y]
nc = len(A) - 1
E = []
for p0 in range(nc):
    p1 = (p0 + 1) % nc
    p2 = (p0 + int(nc / 2)) % nc
    a, b, c = equdroite(A[p0], B[p0], A[p1], B[p1])
    s = sign(A[p2], B[p2], a, b, c)
    #     print("inloop:",p0,a,b,c,s)
    E.append([a, b, c, s, p0, p1])
# print("E:",E)
for p in range(nc):
    for C in E:
        if p != C[4] and p != C[5]:
            a, b, c, s, xp, yp = C[0], C[1], C[2], C[3], A[p], B[p]
            v = sign(xp, yp, a, b, c)
            if s * v < 0:
                #             print("outside:",a,b,c,s,xp,yp)
                print("OUPS!", s, v)
matplotlib.pyplot.plot(A, B)
matplotlib.pyplot.scatter(x, y, color="r")
matplotlib.pyplot.axis("equal")
matplotlib.pyplot.grid()

phg = (int(min(A) / sg) * sg, int(min(B) / sg) * sg)
pbd = (int(max(A) / sg + 1) * sg, int(max(B) / sg + 1) * sg)
nrow = int((pbd[0] - phg[0]) / sg) + 1
ncol = int((pbd[1] - phg[1]) / sg) + 1
# print(phg)
# print(nrow,ncol)
prouge = []
for row in range(nrow):
    for col in range(ncol):
        pp = (phg[0] + sg * row, phg[1] + sg * col)
        if inside(E, pp):
            prouge.append(pp)
xrouge = [ppp[0] for ppp in prouge]
yrouge = [ppp[1] for ppp in prouge]
matplotlib.pyplot.scatter(xrouge, yrouge, color="g")
matplotlib.pyplot.scatter(x, y, color="r")
with open("coordout.csv", "w") as f:
    print("X;Y", file=f)
    for xrouge, yrouge in prouge:
        print(f"{xrouge};{yrouge}", file=f)

matplotlib.pyplot.show()
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557
17 janv. 2023 à 13:16

montre-nous alors le code avec ce read().

0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 17 janv. 2023 à 13:23

Bonjour,

filename est le nom du fichier que tu sélectionnes avec la boite de dialogue askopenfilename

donc (x,y) = filename c'est bizarre

C'est comme si on faisait (x,y) = 'toto.txt'

0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
17 janv. 2023 à 13:23

tu confonds le nom du fichier et son contenu.....

0
LALO_5656 Messages postés 29 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 21 septembre 2024 2
Modifié le 18 janv. 2023 à 12:15

Bonjour sans doute, franchement je suis bloqué.

Yg_be je pas compris votre demande.

0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557
18 janv. 2023 à 15:26

montre-nous le code complet qui te donne l'erreur "TypeError: read expected 2 arguments, got 1".

0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168 > yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024
18 janv. 2023 à 16:37

a mon avis c'est ça:

(x,y) = filename = filedialog.askopenfilename(...)

donc voir ma réponse de 13h36 ci-dessous

0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 18 janv. 2023 à 13:42

Bonjour,

J'espère que tu as bien compris que filename = filedialog.askopenfilename(...)

te rend le nom du fichier que tu as choisi dans la boite de dialogue ? ???

Donc une fois que tu as ce nom, il faut ouvrir le fichier en lecture (mais pas avec os.popen)

et y lire les 2 valeurs de x et y

Tu sais faire ça, au moins ?

Sinon, tu peux jeter un œil ici:

https://pythonforge.com/lire-ou-ecrire-dans-un-fichier-avec-python/

0
LALO_5656 Messages postés 29 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 21 septembre 2024 2
19 janv. 2023 à 20:09

Bonsoir voila ce que j'ai fais comme code mais hélas.

J'obtient l'erreur: 

 (x, y) = contenu
ValueError: too many values to unpack (expected 2)
325010, 325015, 325015, 325010 2077560, 2077560, 2077555, 2077555

# Les 4 coordonnées sources
Coordsources = filedialog.askopenfilename(initialdir="/", title="selectionner le fichier",
                                          filetypes=(("fichier texte", "*.txt"), ("fichier csv", "*.csv")))
# print(Coordsources)
(z) = open(Coordsources, "r")
contenu = z.read()
print(contenu)
(x, y) = contenu
z.close()
0

Bonsoir, tu tentes de faire

>>> x, y = 'blablabla, bla, bla, bla'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)

Forcément, ça ne fonctionne pas.

Ton fichier contient une chaîne de  liste de valeurs, du dois donc :

- Séparer chaque valeurs de ce str par la virgule pour en obtenir une liste de str

- Convertir chacune de ces valeurs en entier

Faire cela est aisé.

0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
20 janv. 2023 à 11:04

Bonjour,

Non seulement il faut convertir en entier, mais il faut aussi qu'il n'y ait que 2 valeurs dans la liste:

x,y = (10,20,30)
ValueError: too many values to unpack (expected 2) : trop de valeurs a récupérer (2 attendues)
0
LALO_5656 Messages postés 29 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 21 septembre 2024 2
Modifié le 24 janv. 2023 à 16:13

Bonsoir à tous,

Merci pour vos réactions. Mamiemando, votre code #19 répond à mes attente, il fonctionne très bien.

Cependant j'ai aussi trouvé cet code qui marche aussi en faisant des input :

x = [int(x) for x in input().split()]

J'ai encore une question.

Peut-on copier les valeurs de l'emprise pour ensuite les coller dans le fichier "coordout.csv" à l'emplacement "P1" de la feuille?

0
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
24 janv. 2023 à 16:32

Bonjour LALO_5656,

Ta question #20 mériterait une nouvelle discussion car c'est un nouveau sujet. Dans les faits, ta question revient à mettre à jour un fichier CSV.

C'est un problème qui a déjà été posé sur le forum (par exemple ici, en utilisant pandas). Dans ton cas, inutile de sortir l'artillerie lourde, tu peux le faire "à la main". Il faut charger en mémoire le fichier csv (comme le fait par exemple la fonction read_coords dans #19), mettre à jour cette structure de données (dans ce que j'ai proposé, une liste), puis réécrire le fichier avec la ou les valeur(s) corrigée(s) à partir de cette structure de données.

Je n'ai pas compris ce que tu appelais les coordonnées P1 (je suppose que c'est le premier point listé dans le fichier ?). Idéalement il faudrait que tu donnes dans la discussion que tu vas ouvrir le fichier de départ et le fichier que tu aimerais obtenir.

Voici à quoi ça pourrait ressembler :

points.csv

0.0;2.2
2.2;5.5
5.5;6.6
6.6;0.0

script.py

import csv

def read_points(f):
    reader = csv.reader(f, delimiter=';')
    return [[float(x) for x in point] for point in reader]

def write_points(f, points): 
    writer = csv.writer(f, delimiter=';')
    for point in points:
        writer.writerow(point)

# Lecture des points
with open("points.csv") as f:
    points = read_points(f)

assert len(points) > 0

# Correction du premier point
points[0] = [-1.1, -1.2]

# Ecriture du fichier de points (on peut utiliser ou non le même fichier)
with open("points.csv", "w") as f:
    write_points(f, points)

Résultat :

(mando@silk) (~) $ cat points.csv 
0.0;2.2
2.2;5.5
5.5;6.6
6.6;0.0

(mando@silk) (~) $ python3 script.py 

(mando@silk) (~) $ cat points.csv 
-1.1;-1.2
2.2;5.5
5.5;6.6
6.6;0.0

Bonne chance

0