Python Forum
Networking Issues - Python GUI client and server connection always freezes
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Networking Issues - Python GUI client and server connection always freezes
#1
So my python program is essentially an investment interface where the client displays the graphical elements like the first page is the login or signup page and then when the credentials of the user are verified against the server which uses an sqlite database to store said entries. Then upon successful login, the user moves on to the next page where there are other elements instantiated. My question is each time I login or signup, a press of either buttons just end up freezing the whole gui and I have to hardclose it. I have tried with a csv file which stores the sql database entries and then use pandas to read said csv to acknowledge proper entry but to no avail. I cannot proceed further without this feature working. Any help is much appreciated. Been trying to debug this for ages now.

Used csv connected to sql database then pandas to read from said csv, does not work and I noticed that nothing was being saved but when running the client, it displays in the terminal sending then proceeds to show the credentials chosen in the login/signup page but I guess the server does not receive these data and as such cannot store them. Here are the server and client codes.

Server codes:
import sqlite3
from sqlite3 import Error
import socket
import threading
import pandas as pd
import yfinance as yf
import os

class Database:
    def __init__(self):
        self.conn = self.create_connection()

    def create_connection(self):
        conn = None
        try:
            conn = sqlite3.connect('clients.db')
            print(f'successful connection with sqlite version {sqlite3.version}')
        except Error as e:
            print(e)
        return conn

    def create_table(self, create_table_sql):
        try:
            c = self.conn.cursor()
            c.execute(create_table_sql)
        except Error as e:
            print(e)

    def setup_database(self):
        sql_create_user_table = """CREATE TABLE IF NOT EXISTS clients (
                                    client_id VARCHAR(20) NOT NULL PRIMARY KEY,
                                    password VARCHAR(255) NOT NULL,
                                    age INT,
                                    initial_investment FLOAT,
                                    investment_type VARCHAR(255)
                                    );"""
        self.create_table(sql_create_user_table)

    def create_user(self, user):
        sql = '''INSERT INTO clients(client_id, password, age, initial_investment, investment_type)
                 VALUES(?,?,?,?,?)'''
        cur = self.conn.cursor()
        cur.execute(sql, user)
        self.conn.commit()
        return cur.lastrowid

    def get_all_users(self):
        cur = self.conn.cursor()
        cur.execute("SELECT * FROM clients")
        return cur.fetchall()

    def user_exists(self, client_id, password):
        cur = self.conn.cursor()
        cur.execute("SELECT * FROM clients WHERE client_id = ? AND password = ?", (client_id, password))
        return len(cur.fetchall()) > 0

    def export_to_csv(self, filename):
        df = pd.read_sql_query("SELECT * FROM clients", self.conn)
        df.to_csv(filename, index=False)

    def import_from_csv(self, filename):
        df = pd.read_csv(filename)
        df.to_sql('clients', self.conn, if_exists='replace', index=False)

class AssetManager:
    @staticmethod
    def get_asset_prices():
        assets = ['ETH-USD', 'DOGE-USD', 'BTC-USD', 'GC=F', 'SI=F']
        prices = yf.download(assets, start='2023-03-18', end='2023-03-19')['Close']
        return prices.iloc[-1].to_dict()

class Server:
    def __init__(self, database, asset_manager):
        self.database = database
        self.asset_manager = asset_manager

    def handle_client(self, client_socket):
        while True:
            data = client_socket.recv(1024).decode("utf-8")
            if not data:
                break
            print(f"Received data: {data}")

        request_type, *request_data = data.split("|")

        if request_type == "signup":
            client_id, password, age, initial_investment, investment_type = request_data
            print(f"Signup data: {client_id}, {password}, {age}, {initial_investment}, {investment_type}")
            if not self.database.user_exists(client_id, password):
                self.database.create_user((client_id, password, age, initial_investment, investment_type))
                response = "signup_success|Account created successfully."
            else:
                response = "signup_failure|Account with this ID and password already exists."
        elif request_type == "login":
            client_id, password = request_data
            if self.database.user_exists(client_id, password):
                response = "login_success|Login successful."
            else:
                response = "login_failure|Invalid ID or password."
        elif request_type == "view_portfolio":
            asset_prices = self.asset_manager.get_asset_prices()
            response = "view_portfolio|"
            for asset, price in asset_prices.items():
                response += f"{asset}: {price}\n"

            all_users = self.database.get_all_users()
            response += "\nList of connected users:\n"
            for user in all_users:
                response += f"{user[0]}: {user[1]}\n"
            if request_type in ["signup", "login"]:
                if "success" in response:
                    self.database.export_to_csv('clients.csv')

            client_socket.sendall(response.encode("utf-8"))

    def start(self):
        if not os.path.exists('clients.csv'):
            self.database.export_to_csv('clients.csv')
        self.database.import_from_csv('clients.csv')

        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server.bind(('localhost', 5000))
        server.listen(5)
        server.settimeout(5)
        print("Server started. Waiting for connections...")

        while True:
            try:
                client, address = server.accept()
                client.settimeout(5)  # Set the timeout for the new socket
                print(f"Connection from {address} has been established.")
                client_thread = threading.Thread(target=self.handle_client, args=(client,))
                client_thread.start()
            except socket.timeout:
                print("No new connection received. Continuing to wait...")

def main():
    db = Database()
    db.setup_database()
    am = AssetManager()
    server = Server(db, am)
    try:
        server.start()
    except KeyboardInterrupt:
        print("Server stopped. Exporting data to 'clients.csv'...")
        db.export_to_csv('clients.csv')
        print("Data exported successfully.")

if __name__ == "__main__":
    main()

Client:
import socket
from tkinter import *
from tkinter import messagebox
from tkinter import simpledialog
import yfinance as yf
import matplotlib.pyplot as plt


class Investment_Interface_App:
    def __init__(self, root):
        self.root = root
        self.root.title("Investment_Interface_App")
        self.root.geometry("400x400")

        self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.client_socket.connect(('localhost', 5000))
        self.client_socket.settimeout(5)

        self.login_signup_frame = Frame(self.root)
        self.login_signup_frame.pack(fill=BOTH, expand=True)

        self.create_login_signup_frame()

    def send_request(self, request):
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client_socket.connect(('localhost', 5000))
        client_socket.sendall(request.encode("utf-8"))
        response = client_socket.recv(4096).decode("utf-8")
        client_socket.close()
        response_type, *response_data = response.split("|")
        if response_type == "signup_success":
            messagebox.showinfo("Success", response_data[0])
        elif response_type == "signup_failure":
            messagebox.showerror("Error", response_data[0])
        elif response_type == "login_success":
            messagebox.showinfo("Success", response_data[0])
            # Add any additional actions to perform upon successful login
        elif response_type == "login_failure":
            messagebox.showerror("Error", response_data[0])
        else:
            messagebox.showerror("Error", "Unknown response type.")
        return response.split("|")

    def login(self):
        self.client_id = self.client_id_entry.get()
        self.password = self.password_entry.get()

        if not self.client_id or not self.password:
            messagebox.showerror("Error", "Please fill in both fields.")
            return

        data = f"login|{self.client_id}|{self.password}"

        response = self.send_request(data)
        if response is None:
            return

        response_status, response_message = response.split("|", 1)
        if response_status == "login_success":
            # Proceed to the next page
            print("Logged in successfully")
        else:
            # Show an error message
            print(f"Login failed: {response_message}")

    def signup(self):
        self.client_id = self.client_id_entry.get()
        self.password = self.password_entry.get()
        self.age = self.age_entry.get()
        self.initial_investment = self.initial_investment_entry.get()

        selected_investment_types = []
        for index in self.investment_type_listbox.curselection():
            selected_investment_types.append(self.investment_type_listbox.get(index))
        self.investment_type = ','.join(selected_investment_types)

        if not self.client_id or not self.password or not self.age or not self.initial_investment or not self.investment_type:
            messagebox.showerror("Error", "Please fill in all fields.")
            return

        if not (18 <= int(self.age) <= 100):
            messagebox.showerror("Error", "Age must be between 18 and 100.")
            return

        data = f"signup|{self.client_id}|{self.password}|{self.age}|{self.initial_investment}|{self.investment_type}"

        response = self.send_request(data)
        if response is None:
            return

        if "|" in response:
            response_status, response_message = response.split("|", 1)
            if response_status == "success":
                messagebox.showinfo("Success", response_message)
            else:
                messagebox.showerror("Error", response_message)
        else:
            messagebox.showerror("Error", f"Unexpected server response: {response}")

    def create_login_signup_frame(self):
        Label(self.login_signup_frame, text="ClientID").grid(row=0, column=0, sticky=W)
        self.client_id_entry = Entry(self.login_signup_frame)
        self.client_id_entry.grid(row=0, column=1)

        Label(self.login_signup_frame, text="Password").grid(row=1, column=0, sticky=W)
        self.password_entry = Entry(self.login_signup_frame, show="*")
        self.password_entry.grid(row=1,column=1)
        self.extra_fields = []
        self.mode = StringVar()
        self.mode.set("login")
        self.mode_button = Button(self.login_signup_frame, text="Switch to Sign Up", command=self.toggle_mode)

        self.action_button = Button(self.login_signup_frame, text="Login", command=self.login_or_signup)

        self.mode_button.grid(row=5, column=0, padx=10, pady=10)
        self.action_button.grid(row=5, column=1, padx=10, pady=10)

    def toggle_mode(self):
        if self.mode.get() == "login":
            self.mode.set("signup")
            self.mode_button.config(text="Switch to Login")
            self.action_button.config(text="Sign Up")
            self.create_signup_frame()
        else:
            self.mode.set("login")
            self.mode_button.config(text="Switch to Sign Up")
            self.action_button.config(text="Login")
            self.remove_signup_frame()

    def create_signup_frame(self):
        age_label = Label(self.login_signup_frame, text="Age")
        age_label.grid(row=3, column=0, sticky=W)
        self.age_entry = Entry(self.login_signup_frame)
        self.age_entry.grid(row=3, column=1)

        initial_investment_label = Label(self.login_signup_frame, text="Initial Investment")
        initial_investment_label.grid(row=4, column=0, sticky=W)
        self.initial_investment_entry = Entry(self.login_signup_frame)
        self.initial_investment_entry.grid(row=4, column=1)

        investment_type_label = Label(self.login_signup_frame, text="Investment Type")
        investment_type_label.grid(row=5, column=0, sticky=W)
        self.investment_type_listbox = Listbox(self.login_signup_frame, selectmode=MULTIPLE)
        self.investment_type_listbox.grid(row=5, column=1)
        for item in ["Ethereum", "Bitcoin", "DogeCoin", "Gold", "Silver"]:
            self.investment_type_listbox.insert(END, item)

        self.extra_fields.extend([age_label, self.age_entry, initial_investment_label, self.initial_investment_entry,
                                  investment_type_label, self.investment_type_listbox])

        self.mode_button.grid(row=6, column=0, padx=10, pady=10)
        self.action_button.grid(row=6, column=1, padx=10, pady=10)

    def remove_signup_frame(self):
        for field in self.extra_fields:
            field.grid_remove()
        self.extra_fields.clear()


    def login_or_signup(self):
        client_id = self.client_id_entry.get()
        password = self.password_entry.get()

        if self.mode.get() == "signup":
            age = self.age_entry.get()
            initial_investment = self.initial_investment_entry.get()
            investment_type = "|".join([self.investment_type_listbox.get(idx) for idx in self.investment_type_listbox.curselection()])
            request = f"signup|{client_id}|{password}|{age}|{initial_investment}|{investment_type}"
        else:
            request = f"login|{client_id}|{password}"

        self.send_request(request)

    def create_account_frame(self):
        self.account_frame = Frame(self.root)
        self.account_frame.pack(fill=BOTH, expand=True)
        self.open_account_button = Button(self.account_frame, text="Open An Account", command=self.open_account)
        self.open_account_button.pack(pady=10)

    def open_account(self):
        self.account_frame.pack_forget()
        self.create_options_frame()

    def create_options_frame(self):
        self.options_frame = Frame(self.root)
        self.options_frame.pack(fill=BOTH, expand=True)

        self.invest_now_button = Button(self.options_frame, text="Invest Now", command=self.invest_now)
        self.invest_now_button.pack(pady=10)

        self.portfolio_viewing_button = Button(self.options_frame, text="Portfolio Viewing",
                                               command=self.view_portfolio)
        self.portfolio_viewing_button.pack(pady=10)

        self.pay_in_out_button = Button(self.options_frame, text="Pay In/Withdraw", command=self.pay_in_out)
        self.pay_in_out_button.pack(pady=10)

    def invest_now(self):
        self.options_frame.pack_forget()
        self.invest_now_frame = Frame(self.root)
        self.invest_now_frame.pack(fill=BOTH, expand=True)

        Label(self.invest_now_frame, text="Investment").grid(row=0, column=0, sticky=W)
        self.investment_choice = StringVar()
        self.investment_menu = OptionMenu(self.invest_now_frame, self.investment_choice,
                                          *["Ethereum", "LiteCoin", "DogeCoin", "Shiba Inu", "Binance Coin", "Gold",
                                            "Silver"])
        self.investment_menu.grid(row=0, column=1)

        Label(self.invest_now_frame, text="Quantity").grid(row=1, column=0, sticky=W)
        self.quantity_entry = Entry(self.invest_now_frame)
        self.quantity_entry.grid(row=1, column=1)

        self.calculate_button = Button(self.invest_now_frame, text="Calculate Value", command=self.calculate_value)
        self.calculate_button.grid(row=2, column=1, pady=10)

    def calculate_value(self):
        investment = self.investment_choice.get()
        quantity = float(self.quantity_entry.get())

        data = f"get_current_price|{investment}"

        response = self.send_request(data)
        if response is None:
            return

        current_price = float(response)

        value = current_price * quantity
        messagebox.showinfo("Investment Value", f"The value of {quantity} {investment} is ${value:.2f}")

    def get_latest_prices(self, investment_types):
        ticker_symbols = {
            "Gold": "GC=F",
            "Silver": "SI=F",
            "Ethereum": "ETH-USD",
            "Bitcoin": "BTC-USD",
            "DogeCoin": "DOGE-USD"
        }

        prices = {}
        for investment in investment_types:
            ticker = yf.Ticker(ticker_symbols[investment])
            latest_price = ticker.info["regularMarketPrice"]
            prices[investment] = latest_price

        return prices

    def view_portfolio(self):
        data = f"view_portfolio|{self.client_id}"

        response = self.send_request(data)
        if response is None:
            return

        if response.startswith("success"):
            portfolio = response[8:]
            investment_types = portfolio.split(",")

            # Get the latest prices
            latest_prices = self.get_latest_prices(investment_types)

            # Calculate the value of each investment type
            quantities = [1, 2, 3]  # Replace this with the actual quantities of the investments
            values = [quantities[i] * latest_prices[investment] for i, investment in  `your text`enumerate(investment_types)]

            # Generate a bar chart
            plt.bar(investment_types, values)
            plt.xlabel("Investment Types")
            plt.ylabel("Value")
            plt.title("Portfolio")
            plt.show()

            messagebox.showinfo("Portfolio", f"Your portfolio: {portfolio}")
        else:
            messagebox.showerror("Error", "Failed to fetch portfolio.")


    def pay_in_out(self):
        self.options_frame.pack_forget()
        self.pay_in_out_frame = Frame(self.root)
        self.pay_in_out_frame.pack(fill=BOTH, expand=True)

        self.pay_in_button = Button(self.pay_in_out_frame, text="Pay In", command=self.pay_in)
        self.pay_in_button.pack(pady=10)
        self.withdraw_button = Button(self.pay_in_out_frame, text="Withdraw", command=self.withdraw)
        self.withdraw_button.pack(pady=10)

    def pay_in(self):
        amount = simpledialog.askfloat("Pay In", "Enter the amount to pay in:", parent=self.root, minvalue=0)
        if amount is None:
            return

        data = f"pay_in|{amount}"

        response = self.send_request(data)
        if response is None:
            return

        if response == "success":
            messagebox.showinfo("Success", f"${amount:.2f} has been successfully added to your account.")
        else:
            messagebox.showerror("Error", "Failed to pay in.")

    def withdraw(self):
        amount = simpledialog.askfloat("Withdraw", "Enter the amount to withdraw:", parent=self.root, minvalue=0)
        if amount is None:
            return

        data = f"withdraw|{amount}"

        response = self.send_request(data)
        if response is None:
            return

        if response == "success":
             messagebox.showinfo("Success", f"${amount:.2f} has been successfully withdrawn from your account.")
        else:
            messagebox.showerror("Error", "Failed to withdraw.")



if __name__ == "__main__":
    root = Tk()
    app = Investment_Interface_App(root)
    root.mainloop()
Larz60+ write Mar-21-2023, 08:13 PM:
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
Fixed for you this time. Please use BBCode tags on future posts.

Attached Files

.py   Client.py (Size: 13 KB / Downloads: 86)
.py   Server.py (Size: 5.61 KB / Downloads: 89)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  I don't know what is wrong (Python and SQL connection) shereen 3 332 Apr-01-2024, 08:56 AM
Last Post: Pedroski55
  No Internet connection when running a Python script basil_555 8 581 Mar-11-2024, 11:02 AM
Last Post: snippsat
  Connection LTspice-Python with PyLTSpice bartel90 0 337 Feb-05-2024, 11:46 AM
Last Post: bartel90
  Virtual Env changing mysql connection string in python Fredesetes 0 375 Dec-20-2023, 04:06 PM
Last Post: Fredesetes
  connection python and SQL dawid294 4 655 Dec-12-2023, 08:22 AM
Last Post: Pedroski55
  Getting "SSL client not supported by this Python installation" error prabirsarkar 0 951 Mar-13-2023, 05:01 PM
Last Post: prabirsarkar
  Issues with "connection timed out" duckredbeard 0 1,459 Dec-31-2022, 10:46 PM
Last Post: duckredbeard
Shocked Issues Installing Pyenv/Python 3.9.1 Brandon_Contactum 1 2,519 Feb-22-2022, 06:32 PM
Last Post: snippsat
  Mysql error message: Lost connection to MySQL server during query tomtom 6 16,001 Feb-09-2022, 09:55 AM
Last Post: ibreeden
  creating python server and client in a pc kucingkembar 4 2,007 Nov-29-2021, 01:37 PM
Last Post: kucingkembar

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020