Why does kivy keep freezing when using python sockets? - sockets

I'm working on a basic client-server desktop app project using kivy & sockets & threading.
The client & server work on it's own, however when I try to integrate it with kivy, python & kivy don't want to respond & yet no definitive error pops up.
Could i have some ideas as to how to fix this?
This is the code that freezes when i run it, if i take away the import server_sock it works as a general gui and doesnt freeze.
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock
import server_sock
import sys
kivy.require("2.1.0") #latest version
class ConnectPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 2
self.add_widget(Label(text="IP:"))
self.ip = TextInput(multiline=False)
self.add_widget(self.ip)
self.add_widget(Label(text="PORT:"))
self.port = TextInput(multiline=False)
self.add_widget(self.port)
self.add_widget(Label(text="USERNAME:"))
self.user = TextInput(multiline=False)
self.add_widget(self.user)
self.join = Button(text="Join")
self.join.bind(on_press=self.join_button)
self.add_widget(Label())
self.add_widget(self.join)
def join_button(self, instance):
port = self.port.text
ip = self.ip.text
user = self.user.text
info = f"Attempting to join {ip}:{port} as {user}"
chat_app.info_page.update_info(info)
chat_app.screen_manager.current = "Info"
Clock.shedule_once(self.connect,1)
def connect(self, _):
port = int(self.port.text)
ip = self.ip.text
user = self.user.text
try:
server_sock.connect(ip, port)
chat_app.create_chat_page()
chat_app.screen_manager.current = "Chat"
except:
show_error(message="not gonna happen")
class InfoPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 1
self.message = Label(halign="center", valign="middle", font_size="30")
self.message.bind(width=self.update_text_width)
self.add_widget(self.message)
def update_info(self,message):
self.message.text = message
def update_text_width(self, *_):
self.message.text_size = (self.message.width*0.9, None)
class ChatPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 1
self.add_widget(Label(text="Hey at least it works till now"))
class ChatApp(App):
def build(self):
self.screen_manager = ScreenManager()
self.connect_page = ConnectPage()
screen = Screen(name="Connect")
screen.add_widget(self.connect_page)
self.screen_manager.add_widget(screen)
self.info_page = InfoPage()
screen= Screen(name="Info")
screen.add_widget(self.info_page)
self.screen_manager.add_widget(screen)
return self.screen_manager
def create_chat_page(self):
self.chat_page = ChatPage()
screen = Screen(name="Chat")
screen.add_widget(self.chat_page)
self.screen_manager.add_widget(screen)
def show_error(message):
chat_app.info_page.update_info(message)
chat_app.screen_manager.current = "Info"
Clock.shedule_once(sys.exit, 10)
if __name__ == "__main__":
chat_app =ChatApp()
chat_app.run()
This is the server_sock file
import socket
import threading
import socket
HOST = '127.0.0.1'
PORT = 55555
server = socket.socket(
socket.AF_INET,
socket.SOCK_STREAM
)
try:
server.bind((HOST, PORT))
except:
print(f'unable to bind to {HOST} and {PORT}')
server.listen()
print(f"Listening for connections on {HOST}: {PORT}")
clients = []
nicknames = []
def broadcast(message):
for client in clients:
client.send(message)
def message_recv(client):
while True:
try:
message = client.recv(2048)
broadcast(message)
except:
index = clients.index(client)
clients.remove(client)
nickname = nicknames[index]
broadcast(f'{nickname} left the chat'.encode('ascii'))
nicknames.remove(nickname)
break
def recieve():
while True:
client, address = server.accept()
print(f"Connected with {str(address)}")
client.send("SOMETHING".encode('ascii'))
nickname = client.recv(2048).decode('ascii')
nicknames.append(nickname)
clients.append(client)
print(f"Nickname of the client is {nickname}")
broadcast(f"{nickname} joined the chat".encode('ascii'))
client.send("Connected to the server".encode('ascii'))
thread = threading.Thread(target=message_recv, args=(client,))
thread.start()
print("Server is listening")
recieve()

Related

FastAPI StreamingResponse with picamera2 - browser refresh problem

I'm trying to make FastAPI server which streams MJPEG from Raspberry Pi via picamera2 library. It works, but when I reload browser on /mjpeg multiple times, it will stuck. But with this example it works perfectly - you can reload browsers as many times as you want. Can you spot the problem?
For server I'm using uvicorn with default settings.
Thanks!
import io
import os
from threading import Condition
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from picamera2 import Picamera2
from picamera2.encoders import JpegEncoder
from picamera2.outputs import FileOutput
from fastapi.responses import HTMLResponse, StreamingResponse
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins="http://localhost:8000",
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class StreamingOutput(io.BufferedIOBase):
def __init__(self):
self.frame = None
self.condition = Condition()
def write(self, buf):
with self.condition:
self.frame = buf
self.condition.notify_all()
picam2 = Picamera2()
picam2.configure(picam2.create_video_configuration(main={"size": (640, 480)}))
output = StreamingOutput()
picam2.start_recording(JpegEncoder(), FileOutput(output))
def get_frame():
try:
while True:
with output.condition:
output.condition.wait()
frame = output.frame
yield (
b"--frame\r\n" b"Content-Type: image/jpeg\r\n\r\n" + frame + b"\r\n"
)
except Exception as e:
print("Error! Frames")
#app.get("/mjpeg", response_class=StreamingResponse)
def mjpeg(request: Request):
try:
frames = get_frame()
response = StreamingResponse(
frames,
headers={
"Cache-Control": "no-cache, private",
"Pragma": "no-cache",
},
media_type="multipart/x-mixed-replace; boundary=frame",
)
return response
except Exception as e:
print("Error! Route")

ChannelsLiveServerTestCase equivalent for pytest

In pytest-django there is a builtin fixture live_server though it seems like this server (that is actually based on LiveServerTestCase) can't handle web-sockets or at least won't interact with my asgi.py module.
How can one mimic that fixture in order to use ChannelsLiveServerTestCase instead? Or anything else that will run a test-database and will be able to serve an ASGI application?
My goal eventually is to have as close to production environment as possible, for testing and being able to test interaction between different Consumers.
P.S: I know I can run manage.py testserver <Fixture> on another thread / process by overriding django_db_setup though I seek for a better solution.
You can implement a channels_live_server fixture based on the implementations of:
live_server fixture, which instantiates
LiveServer helper, which starts LiveServerThread, and
ChannelsLiveServerTestCase, which starts DaphneProcess.
#medihack implemented it at https://github.com/pytest-dev/pytest-django/issues/1027:
from functools import partial
from channels.routing import get_default_application
from daphne.testing import DaphneProcess
from django.contrib.staticfiles.handlers import ASGIStaticFilesHandler
from django.core.exceptions import ImproperlyConfigured
from django.db import connections
from django.test.utils import modify_settings
def make_application(*, static_wrapper):
# Module-level function for pickle-ability
application = get_default_application()
if static_wrapper is not None:
application = static_wrapper(application)
return application
class ChannelsLiveServer:
host = "localhost"
ProtocolServerProcess = DaphneProcess
static_wrapper = ASGIStaticFilesHandler
serve_static = True
def __init__(self) -> None:
for connection in connections.all():
if connection.vendor == "sqlite" and connection.is_in_memory_db():
raise ImproperlyConfigured(
"ChannelsLiveServer can not be used with in memory databases"
)
self._live_server_modified_settings = modify_settings(ALLOWED_HOSTS={"append": self.host})
self._live_server_modified_settings.enable()
get_application = partial(
make_application,
static_wrapper=self.static_wrapper if self.serve_static else None,
)
self._server_process = self.ProtocolServerProcess(self.host, get_application)
self._server_process.start()
self._server_process.ready.wait()
self._port = self._server_process.port.value
def stop(self) -> None:
self._server_process.terminate()
self._server_process.join()
self._live_server_modified_settings.disable()
#property
def url(self) -> str:
return f"http://{self.host}:{self._port}"
#pytest.fixture
def channels_live_server(request):
server = ChannelsLiveServer()
request.addfinalizer(server.stop)
return server
#aaron's solution can't work, due to pytest-django conservative approach for database access.
another proccess wouldn't be aware that your test has database access permissions therefore you won't have database access. (here is a POC)
Using a scoped fixture of daphne Server suffice for now.
import threading
import time
from functools import partial
from django.contrib.staticfiles.handlers import ASGIStaticFilesHandler
from django.core.exceptions import ImproperlyConfigured
from django.db import connections
from django.test.utils import modify_settings
from daphne.server import Server as DaphneServer
from daphne.endpoints import build_endpoint_description_strings
def get_open_port() -> int:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("", 0))
s.listen(1)
port = s.getsockname()[1]
s.close()
return port
def make_application(*, static_wrapper):
# Module-level function for pickle-ability
if static_wrapper is not None:
application = static_wrapper(your_asgi_app)
return application
class ChannelsLiveServer:
port = get_open_port()
host = "localhost"
static_wrapper = ASGIStaticFilesHandler
serve_static = True
def __init__(self) -> None:
for connection in connections.all():
if connection.vendor == "sqlite" and connection.is_in_memory_db():
raise ImproperlyConfigured(
"ChannelsLiveServer can not be used with in memory databases"
)
self._live_server_modified_settings = modify_settings(ALLOWED_HOSTS={"append": self.host})
self._live_server_modified_settings.enable()
get_application = partial(
make_application,
static_wrapper=self.static_wrapper if self.serve_static else None,
)
endpoints = build_endpoint_description_strings(
host=self.host, port=self.port
)
self._server = DaphneServer(
application=get_application(),
endpoints=endpoints
)
t = threading.Thread(target=self._server.run)
t.start()
for i in range(10):
time.sleep(0.10)
if self._server.listening_addresses:
break
assert self._server.listening_addresses[0]
def stop(self) -> None:
self._server.stop()
self._live_server_modified_settings.disable()
#property
def url(self) -> str:
return f"ws://{self.host}:{self.port}"
#property
def http_url(self):
return f"http://{self.host}:{self.port}"
#pytest.fixture(scope='session')
def channels_live_server(request, live_server):
server = ChannelsLiveServer()
request.addfinalizer(server.stop)
return server

OSError: [WinError 10038] An operation was attempted on something that is not a socket what is the problem?

im running a chat app on my computer and i tried to send a message and this ERROR accured. it suppose to send a " will joind the chat" and another message " connected to server" after that i should send my message to the group and it didnt worked.
any ideas?
import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
import socket
import threading
kivy.require("1.9.0")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
class MyRoot(BoxLayout):
def __init__(self):
super(MyRoot, self).__init__()
def send_message(self):
client.send(f"{self.nickname_text.text}: {self.message_text.text}".encode('utf-8'))
def connect_to_server(self):
if self.nickname_text != "":
client.connect((self.ip_text.text, 9999))
message = client.recv(1024).decode('utf-8')
if message == "NICK":
client.send(self.nickname_text.text.encode('utf-8'))
self.send_btn.disabled = False
self.message_text.disabled = False
self.connect_btn.disabled = True
self.ip_text.disabled = True
self.make_invisible(self.connection_grid)
self.make_invisible(self.connect_btn)
thread = threading.Thread(target=self.receive)
thread.start()
def make_invisible(self, widget):
widget.visible = False
widget.size_hint_x = None
widget.size_hint_y = None
widget.height = 0
widget.width = 0
widget.text = ""
widget.opacity = 0
def receive(self):
stop = False
while not stop:
try:
message = client.recv(1024).decode('utf-8')
self.chat_text.text += message + "\n"
except:
print("ERROR")
client.close()
stop = True
class TraboChat(App):
def build(self):
return MyRoot()
trabo_chat = TraboChat()
trabo_chat.run()
serve.py:
import socket
import threading
HOST = socket.gethostbyname(socket.gethostname())
PORT = 9999
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
server.listen()
clients = []
nicknames = []
def broadcast(message):
for client in clients:
client.send(message)
def handle_connection(client):
stop = False
while not stop:
try:
message = client.recv(1024)
broadcast(message)
except:
index = clients.index(client)
clients.remove(client)
nickname = nicknames[index]
nicknames.remove(nickname)
broadcast(f"{nickname} left the chat!".encode('utf-8'))
stop = True
def main():
print("server is running..")
while True:
client, addr = server.accept()
print(f"connected to {addr}")
client.send("NICK".encode('utf-8'))
nickname = client.recv(1024).decode('utf-8')
nicknames.append(nickname)
clients.append(client)
print(f"Nickname is {nickname}")
broadcast(f"{nickname} join the chat!")
client.send("You are now connected".encode('utf-8'))
thread = threading.Thread(target=handle_connection, args=(client,))
if name == 'main':
main()

How to use database models in Python Flask?

I'm trying to learn Flask and use postgresql with it. I'm following this tutorial https://realpython.com/flask-by-example-part-2-postgres-sqlalchemy-and-alembic/, but I keep getting error.
Cannot import name 'AorticStenosis' from partially initialized module 'models' (most likely due to a circular import)
I understand the problem, but I can't figure out how to fix it. So, I started playing around and try to use the steps by step tutorial on something that I'm working on, but I still get the same problem.
Here's my attempt:
Models.py
from app import db
class AorticStenosis(db.Model):
__tablename__ = 'wvu-model'
id = db.Column(db.Integer, primary_key=True)
ip_address = db.Column(db.String())
date_created = db.Column(db.DateTime, default=datetime.utcnow)
e_prime = db.Column(db.Float())
LVMi = db.Column(db.Float())
A = db.Column(db.Float())
LAVi = db.Column(db.Float())
E_e_prime = db.Column(db.Float())
EF = db.Column(db.Float())
E = db.Column(db.Float())
E_A = db.Column(db.Float())
TRV = db.Column(db.Float())
prediction = db.Column(db.String())
def __init__(self, ip_address, e_prime, LVMi, A, E_e_prime, EF, E, E_A, TRV, prediction):
print('initialized')
self.ip_address = ip_address
self.e_prime = e_prime
self.LVMi = LVMi
self.A = A
self.LAVi = LAVi
self.E_e_prime = E_e_prime
self.EF = EF
self.E = E
self.E_A = E_A
self.TRV = TRV
self.prediction = prediction
def __repr__(self):
return '<id {}>'.format(self.id)
app.py
import os
import ast
import bcrypt
from flask import Flask, redirect, render_template, request, session, url_for
import flask_login
from flask_sqlalchemy import SQLAlchemy
from bigml.deepnet import Deepnet
from bigml.api import BigML
import pickle as pkl
import sklearn
app = Flask(__name__)
if app.config['ENV'] == 'production':
app.config.from_object('as_config.ProductionConfig')
else:
app.config.from_object("config.DevelopmentConfig")
# app.config.from_pyfile('as_config.py')
# app.config.from_object(os.environ['APP_SETTINGS'])
# app.config.from_object('as_config.DevelopmentConfig')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
from models import AorticStenosis
login_key = app.config['LOGIN_KEY']
api_key = app.config['API_KEY']
model = app.config['MODEL']
api = BigML(login_key, api_key)
deepnet = Deepnet(model, api=api)
scaler = pkl.load(open("scaler.pkl", "rb"))
#app.route("/", methods=["GET", "POST"])
def home():
prediction = None
if request.method == "POST":
form_data = [
float(request.form.get("e_prime")),
float(request.form.get("LVMi")),
float(request.form.get("A")),
float(request.form.get("LAVi")),
float(request.form.get("E_e_prime")),
float(request.form.get("EF")),
float(request.form.get("E")),
float(request.form.get("E_A")),
float(request.form.get("TRV"))
]
form_data = scaler.transform([form_data])[0]
print(form_data)
prediction = str(deepnet.predict({
"e_prime": form_data[0],
"LVMi": form_data[1],
"A": form_data[2],
"LAVi": form_data[3],
"E_e_prime": form_data[4],
"EF": form_data[5],
"E": form_data[6],
"E_A": form_data[7],
"TRV": form_data[8]
}, full=True))
prediction = ast.literal_eval(prediction)
print(prediction)
## get ip address from the user
ip_address = request.environ['REMOTE_ADDR']
print("ip_address: ", ip_address)
try:
aorticStenosis = AorticStenosis(
ip_address = ip_address,
e_prime = form_data[0],
LVMi = form_data[1],
A = form_data[2],
LAVi = form_data[3],
E_e_prime = form_data[4],
EF = form_data[5],
E = form_data[6],
E_A = form_data[7],
TRV = form_data[8]
)
db.session.add(aorticStenosis)
db.session.commit()
except Exception as e:
print(str(e))
if prediction["prediction"] == "1":
prediction["prediction"] = "Low Risk"
prediction["probability"] = round(
1 - prediction["probability"], 6)
elif prediction["prediction"] == "2":
prediction["prediction"] = "High Risk"
else:
prediction["prediction"] = "No prediction was made!"
return render_template("home.html",
prediction=prediction["prediction"],
probability=prediction["probability"])
else:
return render_template("home.html")
if __name__ == "__main__":
app.run(host="0.0.0.0", port="8000")
I made a new file database.py and defined db there.
database.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def init_app(app):
db.init_app(app)
app.py
import database
...
database.init_app(app)
models.py
from database import db
...

Socket class in python 3

I have made a class in python 3 and i can't figure why i can't send the information for the server to client. Server and client are using the same class.
class mysocket:
receive_string_buffer_len = 0
active_instance = 0
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.receive_string_buffer = ''
self.send_string_buffer = ''
self.host = 'localhost'
self.port = 30000 + self.active_instance
self.active_instance += 1
def connect(self):
self.sock.connect((self.host,self.port))
def mysend(self):
try:
sent = self.sock.send(self.send_string_buffer)
except socket.error:
print('socket connection broken')
def myreceive(self):
try:
self.receive_string_buffer = self.sock.recv(512)
except socket.error:
print('socket connection broken')
finally: return self.receive_string_buffer
Client code:
Client_socket1 = mysocket()
Client_socket1.connect()
print(Client_socket1.myreceive().decode('ascii'))
Server code:
Server_socket1 = mysocket()
Server_socket1.bind(('', 30000))
Server_socket1.listen(1)
client1, add = Server_socket1.accept()
Server_socket1.send_string_buffer = ' alo '
Server_socket1.mysend().encode('ascii')
The problem is that it's not working. I am new to python programing and new to sockets so if i done stupid mistakes please tell me .
Thanks to anyone that will read this.
You are sending data on the listening socket instead of the client-server socket returned by accept().
Rgds,
Martin
I dont think "Server_socket1.mysend().encode('ascii')" is valid especially since mysend() doesn't return anything to encode (and you do nothing with return value from encode()). Also you need to encode your data before it can be sent.
I think you will find asynchat module much easier to handle sockets. Just sub class it like:
import threading
class mysocket(asynchat.async_chat):
terminator = b'\n'
def __init__(self,sock=None):
asynchat.async_chat.__init__(self,sock)
self.create_socket()
self.connect(('127.0.0.1',6667))
def handle_connect(self):
pass
def handle_close(self):
pass
def collect_incoming_data(self, data):
pass
def found_terminator(self):
pass
def sockwrite(self,text=None):
# Avoid conflict with text=''
if (text == None):
text = ''
text += '\n'
self.sendall(bytes(text,'latin-1'))
chatsock = {}
def main():
chatsock['a'] = mysocket()
socketloop = threading.Thread(target=asyncore.loop, daemon=1)
socketloop.start()
while True:
pass
if __name__ == "__main__":
main()