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)
Related
I am trying to learn how to use threading with networking and need to stop a thread if a connection is closed. I have a list of multiple connections and a thread that checks if they are still open.
If a connection has closed i need to terminate the GetData() thread but i don't know how to do that without checking for an exit event every loop. The problem is that the GetData() thread doesn't loop but sits at line 25 and waits for a response. If the connection has closed it never gets a response and just keeps sitting there until i kill the program.
How do i kill a thread outside of the thread. I understand that this is not easily done with threading but is there maybe some other library that allows this? I also tried using multiprocessing instead but i couldn't get it to work so i just gave up on that.
from threading import Thread
import socket
def MakeSocket():
try:
global MainSocket
MainSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print ("Socket successfully created")
except socket.error as err:
print ("socket creation failed with error %s" %(err))
MainSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
MainSocket.bind(('', 1337))
MainSocket.listen(5)
global c
global addr
c, addr = MainSocket.accept()
Thread(target=GetData, args=()).start()
Thread(target=CheckIfOpen, args=()).start()
def GetData():
while True:
try:
#Try to recieve data from connection.
RecievedData = c.recv(4096).decode()
print(RecievedData)
except:
print ("\nError: GetData failed.\n")
return
def CheckIfOpen():
while True:
#wait 5 sec between each test
time.sleep(5)
try:
#try to send data "test".
c.send("test".encode())
except:
#if it fails then the connection has been closed. Close the GetData thread
#Don't know how to close the GetData thread
MakeSocket()
I know this looks silly but it isn't all my code. I just changed it a bit and included the important parts. It still contains the same problem. I don't have all those global variables in my actual code.
I realized what was wrong.
https://reddit.com/r/learnpython/comments/kx925z/terminating_thread_thats_waiting/
u/oefd pointed something i missed out in the comments.
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
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
I have just written a very simple udp chatting program for fun. It worked as supposed but now I have no ideas how to safely exit it. It seems that calling sys.exit() is not acceptable due to the problem here: Why does sys.exit() not exit when called inside a thread in Python?
Simply raising signals by ctrl + c will fail because it will be intercepted by raw_input().
Is there any decent way to deal with it?
Here is my code snippet:
import socket
import threading
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
address = ('192.168.1.xxx', 31500)
target_address = ('192.168.1.xxx', 31500)
s.bind(address)
print('waiting for input...')
def rcv():
while True:
data, addr = s.recvfrom(2048)
if not data:
continue
print 'Received: #### ', data
print '\n'
def send():
while True:
msg = raw_input()
if not msg:
continue
s.sendto(msg, target_address)
t1 = threading.Thread(target = rcv)
t2 = threading.Thread(target = send)
t1.start()
t2.start()
Replacing my previous answer:
I modified your code to:
import socket
import threading
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
address = ('192.168.1.xxx', 31500)
target_address = ('192.168.1.xxx', 31500)
s.bind(address)
EXIT_MSG_GUARD = "#Quit!"
print('waiting for input...')
def rcv():
while True:
data, addr = s.recvfrom(2048)
if not data:
continue
print 'Received: #### ', data
print '\n'
def send():
while True:
msg = raw_input()
if not msg:
continue
else:
s.sendto(msg, target_address)
if msg == EXIT_MSG_GUARD:
return
t1 = threading.Thread(target = rcv)
t2 = threading.Thread(target = send)
t1.setDaemon(True)
t1.start()
t2.start()
There are 2 things that I did:
Add a message guard (in my example #Quit!, but you can change it to anything you like): when the user inputs that text, after sending it, the t2 thread ends.
Make thread t1 daemonic, meaning that when the main thread and all the non daemon threads will end, this will end too, and the program will exit.
Note: Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.
As an alternative to daemon threads, you could use the solution posted here (beware of the limitations as well!). It is nicer (and recommended) but, will require more work including a little bit of change to your rcv function
I am writing a simple client-server program in python. In the client program, I am creating two threads (using Python's threading module), one for receiving, one for sending. The receiving thread continuously receives strings from the server side; while the sending thread continuously listens to the user input (using raw_input()) and send it to the server side. The two threads communicate using a Queue (which is natively synchronized, LIKE!).
The basic logic is like following:
Receiving thread:
global queue = Queue.Queue(0)
def run(self):
while 1:
receive a string from the server side
if the string is QUIT signal:
sys.exit()
else:
put it into the global queue
Sending thread:
def run(self):
while 1:
str = raw_input()
send str to the server side
fetch an element from the global queue
deal with the element
As you can see, in the receiving thread, I have a if condition to test whether the server has sent a "QUIT signal" to the client. If it has, then I want the whole program to stop.
The problem here is that for most of its time, the sending thread is blocked by "raw_input()" and waiting for the user input. When it is blocked, calling "sys.exit()" from the other thread (receiving thread) will not terminate the sending thread immediately. The sending thread has to wait for the user to type something and hit the enter button.
Could anybody inspire me how to get around with this? I do not mind using alternatives of "raw_input()". Actually I do not even mind changing the whole structure.
-------------EDIT-------------
I am running this on a linux machine, and my Python version is 2.7.5
You could just make the sending thread daemonic:
send_thread = SendThread() # Assuming this inherits from threading.Thread
send_thread.daemon = True # This must be called before you call start()
The Python interpreter won't be blocked from exiting if the only threads left running are daemons. So, if the only thread left is send_thread, your program will exit, even if you're blocked on raw_input.
Note that this will terminate the sending thread abruptly, no matter what its doing. This could be dangerous if it accesses external resources that need to be cleaned up properly or shouldn't be interrupted (like writing to a file, for example). If you're doing anything like that, protect it with a threading.Lock, and only call sys.exit() from the receiving thread if you can acquire that same Lock.
The short answer is you can't. input() like a lot of such input commands is blocking and it's blocking whether everything about the thread has been killed. You can sometimes call sys.exit() and get it to work depending on the OS, but it's not going to be consistent. Sometimes you can kill the program by deferring out to the local OS. But, then you're not going to be widely cross platform.
What you might want to consider if you have this is to funnel the functionality through the sockets. Because unlike input() we can do timeouts, and threads and kill things rather easily. It also gives you the ability to do multiple connections and maybe accept connections more broadly.
import socket
import time
from threading import Thread
def process(command, connection):
print("Command Entered: %s" % command)
# Any responses are written to connection.
connection.send(bytes('>', 'utf-8'))
class ConsoleSocket:
def __init__(self):
self.keep_running_the_listening_thread = True
self.data_buffer = ''
Thread(target=self.tcp_listen_handle).start()
def stop(self):
self.keep_running_the_listening_thread = False
def handle_tcp_connection_in_another_thread(self, connection, addr):
def handle():
while self.keep_running_the_listening_thread:
try:
data_from_socket = connection.recv(1024)
if len(data_from_socket) != 0:
self.data_buffer += data_from_socket.decode('utf-8')
else:
break
while '\n' in self.data_buffer:
pos = self.data_buffer.find('\n')
command = self.data_buffer[0:pos].strip('\r')
self.data_buffer = self.data_buffer[pos + 1:]
process(command, connection)
except socket.timeout:
continue
except socket.error:
if connection is not None:
connection.close()
break
Thread(target=handle).start()
connection.send(bytes('>', 'utf-8'))
def tcp_listen_handle(self, port=23, connects=5, timeout=2):
"""This is running in its own thread."""
sock = socket.socket()
sock.settimeout(timeout)
sock.bind(('', port))
sock.listen(connects) # We accept more than one connection.
while self.keep_running_the_listening_thread:
connection = None
try:
connection, addr = sock.accept()
address, port = addr
if address != '127.0.0.1': # Only permit localhost.
connection.close()
continue
# makes a thread deals with that stuff. We only do listening.
connection.settimeout(timeout)
self.handle_tcp_connection_in_another_thread(connection, addr)
except socket.timeout:
pass
except OSError:
# Some other error.
if connection is not None:
connection.close()
sock.close()
c = ConsoleSocket()
def killsocket():
time.sleep(20)
c.stop()
Thread(target=killsocket).start()
This launches a listener thread for the connections set on port 23 (telnet), and you connect and it passes that connection off to another thread. And it starts a killsocket thread that disables the various threads and lets them die peacefully (for demonstration purposes). You cannot however connect localhost within this code, because you'd need input() to know what to send to the server, which recreates the problem.