I am writing a threaded Python script for the first time and running into some trouble. The general idea is that a Raspberry Pi receives data from a Bluetooth connection, this data is then used to create a thread that calls the start_laps method. Once this thread is started, I need to continue listening for new data to determine if the thread should be killed. However, my code is not continuing execution after the thread is started. What would cause this?
import json
import bluetooth
import threading
import timed_LEDs
import subprocess
import ast
def start_laps(delay, lap_times):
timed_LEDs.start_LEDs(delay, lap_times)
# put pi in discoverable
subprocess.call(['sudo', 'hciconfig', 'hci0', 'piscan'])
server_socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
port = 1
server_socket.bind(("", port))
server_socket.listen(1)
client_socket, address = server_socket.accept()
print("Accepted connection from ", address)
threads = []
while True:
print("RECEIVING")
data = client_socket.recv(1024)
data = json.loads(data.decode())
print(data)
if(data["lap_times"]):
print("STARTING THREAD")
t = threading.Thread(target=start_laps(int(data["delay"]), ast.literal_eval(data["lap_times"])))
threads.append(t)
t.start()
elif data == "stop":
print("Stop dat lap")
else:
print(data)
client_socket.close()
You are using the threading module wrong.
This line
threading.Thread(target=start_laps(int(data["delay"]), ast.literal_eval(data["lap_times"])))
executes the function start_laps, which obviously blocks the program. What you want is the following:
threading.Thread(target=start_laps, args=(int(data["delay"]), ast.literal_eval(data["lap_times"])))
This executes the function in the created Thread with the given args
Related
I am trying to create a sockets server (TCP/IP) and inside it based on few data from client I am scheduling few background jobs.
following code is working ->
import schedule
import time
def test1():
print('hi from 1')
def test2():
print('hi from test2')
while True:
schedule.run_pending()
time.sleep(1)
Then I tried following thing with socket server then its not executing the jobs/function. Can someone help me what's happening here.
Not working code
import schedule
import time
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 8009)
print('starting up on {} port {}'.format(*server_address))
sock.bind(server_address)
# Listen for incoming connections
sock.listen(1)
def test1():
print('hi from 1')
def test2():
print('hi from test2')
schedule.every(1).minutes.do(test1)
schedule.every(2).minutes.do(test2)
while True:
schedule.run_pending()
time.sleep(1)
print('waiting for a connection')
connection, client_address = sock.accept()
data = connection.recv(1024)
result = data.decode('utf-8')
print('data recived from clinet : ', result)
Thing I am trying to achieve is I want to create python socket server which
will accept request from node client's and based on clients data I want to schedule few jobs in python. for this I am using socket, schedule moduls from python to create socket server and schedule jobs respective and net module at node js's client for sending data to python server.
Please explain your problem in more detail. sock.accept is blocking, so the loop is blocking, is this your problem?
To prevent the program from blocking you can run the scheduler loop in a separate thread and the acceptance loop also in a separate thread too. Create a main thread to manage your child threads. Have a look at the module threading.
Maybe it makes sense to use an other scheduler library that can handle threading, see here.
Disclosure: I'm one of the authors of the scheduler library
I'm new to socket programming in Python and I'm trying to write a chatroom application, but I have a problem which is it each client should press enter in order to receive messages from other clients.
#my client side code
import socket
import sys
client_sock = socket.socket()
port = int(sys.argv[1])
client_sock.connect(('127.0.0.1', port))
print("Connected to server. start sending messages")
while True:
sending_message = input('> ')
if sending_message:
client_sock.send(sending_message.encode())
receiving_message = client_sock.recv(1024)
if receiving_message:
print(receiving_message.decode())
input pauses your program. Thus, either you can't use input blindly, or you have to use threads. Using threads is easier than the alternative (using select to figure out what to do next). Have one thread for input and sending, one thread for receiving and printing.
Here's a trivial rewrite of your code:
import threading
import socket
import sys
client_sock = socket.socket()
port = int(sys.argv[1])
client_sock.connect(('127.0.0.1', port))
print("Connected to server. start sending messages")
def sender():
while True:
sending_message = input('> ')
if sending_message:
client_sock.send(sending_message.encode())
def receiver():
while True:
receiving_message = client_sock.recv(1024)
if receiving_message:
print(receiving_message.decode())
sender_thread = threading.Thread(target=sender)
receiver_thread = threading.Thread(target=receiver)
sender_thread.start()
receiver_thread.start()
sender_thread.join()
receiver_thread.join()
Here is my problem. I have a server on lua which sends data via socket. Data go constantly - it is a stream of exchange transactions. My python script as client should receive data.
def listen():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostname()
sock.connect(("localhost", 1111))
with BytesIO() as response_bytes:
while True:
try:
fragment = sock.recv(8196)
print("Фрагмент: {}".format(fragment))
except Exception:
pass
if __name__ == "__main__":
t2 = threading.Thread(listen())
t2.start()
while True:
print ("test")
Main thread wait sock.recv(8196) line. I want that data from a socket were accepted in parallel, and the main stream continued to work. The current code blocks performance of main until listen is executed. I am not familiar with multiple tasks in Python. What decisions can be?
You have to pass the listen function to threading.Thread(). You're calling the function in the main thread, waiting for it to finish, and then passing its return value (which is just None, since the function never returns anything).
t2 = threading.Thread(target = listen)
This is my code:
socketcheck.py
import time
import subprocess
subprocess.Popen(["python", "server.py"])
for i in range(10):
time.sleep(2)
print i
def print_from_server(data):
print data
server.py
import socket
from socketcheck import print_from_server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost',3005))
client_connected = 1
while 1:
s.listen(1)
conn, addr = s.accept()
data = conn.recv(1024)
if data:
client_connected = 0
else: break
if client_connected == 0:
print 'data received'
print_from_server(data)
client_connected = 1
conn.sendall(data)
client.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost',3005))
s.sendall('Hello, world')
data = s.recv(1024)
#s.close()
print 'Received', repr(data)
What I am trying to do here is, run socketcheck.py which runs server.py in background and listens for a client connection. So whatever data the client sends, I want to pass it on to socketcheck.py. Is this valid? If so, then how do I achieve it?
Now when I try and run socketcheck.py, the for loop is running indefinitely.
Thanks :)
EDIT:
This initially I tried as a single program, but until the client gets connected, the rest of the program doesn't execute(blocking), with the setblocking(0) the program flow wouldn't stop but when the client connects to server it doesn't print(do anything). The server code looked something like this:
import socket
from socketcheck import print_from_server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost',3005))
s.setblocking(0)
while 1:
try:
s.listen(1)
conn, addr = s.accept()
conn.setblocking(0)
data = conn.recv(1024)
if not data: break
print 'data received'
conn.sendall(data)
except:
print 'non blocking'
print 'the lengthy program continues from here'
The reason why your program crashes your computer is simple:
You have a while loop which calls print_from_server(data), and each time it calls it, a new subprocess gets created via subprocess.Popen(["python", "server.py"]).
The reason for creating a new popen each time is a bit more complicated: You open a new server.py program in socketcheck.py. If this new server.py program calls print_from_server(data), this is the first time print_from_server(data) gets called (for the new server.py program). So the global commands (such as popen) are executed, since they are always executed once.
The number of processes running will explode quickly and you computer crashes.
One additional remark: You cannot print to console with a print command in a subprocess, since there is no console attached to that subprocess, you can only print to file. If you do that, you'll see that this output explodes quickly from all the processes.
Put socketcheck.py and server.py into one program and everything works fine, or explain why you need two programs.
The functionality can be easily achieved with multithreading :)
I have a client.py and a server.py. The client receives occasional messages from the server. The client can also send messages to the server.
Because raw_input appears to block the main thread, when the client receives a message from the server, it can't print to the console, and requires raw_input to finish first.
I've tried to use multithreading to get around this, but in the following code, the raw_input doesn't even get called. The following is client.py
import socket
import sys
import threading
BUFFER_SIZE = 1024
def listen_for_server_response(s):
while 1:
data = s.recv(BUFFER_SIZE)
print(data)
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((sys.argv[1], int(sys.argv[2])))
thread = threading.Thread(target = listen_for_server_response(s))
thread.start()
while 1:
command = raw_input("Command: ")
s.send(command)
if __name__ == "__main__":
main()
Any help on this is much appreciated!
this seems like bad design but you need to call threading with a callable function
thread = threading.Thread(target = listen_for_server_response,args=(s,))
thread.start()
by calling it like you do in the example you are calling it before the thread starts and just looping forever ... you dont even make it to thread.start