I was trying to write a chat for a local network (the same with one represented in this tutorial). And when executing the code there have occured some mistakes. First of all,when one of the clients stops it's work with ctrl+c combination the command line of this client throws this exception
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Users\Samsung-PC\AppData\Local\Programs\Python\Python35-
32\lib\threading.py", line 914, in _bootstrap_inner
self.run()
File "C:\Users\Samsung-PC\AppData\Local\Programs\Python\Python35-
32\lib\threading.py", line 862, in run
self._target(*self._args, **self._kwargs)
File "chat.py", line 39, in send_message
self.s.send(bytes(input(""),'utf-8'))
EOFError
and the client still works whithout exiting the program. The work of this client stops only when another client connects to the server. Then,another problem is that server crashes with that exception when one of the clients closes his widow with chat.
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Users\Samsung-PC\AppData\Local\Programs\Python\Python35-
32\lib\threading.py", line 914, in _bootstrap_inner
self.run()
File "C:\Users\Samsung-PC\AppData\Local\Programs\Python\Python35-
32\lib\threading.py", line 862, in run
self._target(*self._args, **self._kwargs)
File "chat.py", line 14, in handler
data=c.recv(1024)
ConnectionResetError: [WinError 10054]
And here is the code
import socket
import threading
import sys
class Server:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
connections = []
def __init__(self):
self.s.bind(('192.168.56.1',9090))
self.s.listen(1)
def handler(self,c,a):
while True:
data=c.recv(1024)
for connection in self.connections:
connection.send(data)
if not data:
self.connections.remove(c)
c.close()
print(str(a[0])+':'+str(a[1]),'disconnected')
break
def run(self):
while True:
c,a =self.s.accept()
cThread=threading.Thread(target=self.handler,args=(c,a))
cThread.daemon=True
cThread.start()
self.connections.append(c)
print(str(a[0])+':'+str(a[1]),'connected')
class Client:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
def send_message(self):
while True:
self.s.send(bytes(input(""),'utf-8'))
def __init__(self,addr):
self.s.connect((addr,9090))
iThread=threading.Thread(target=self.send_message)
iThread.daemon=True
iThread.start()
while True:
data=self.s.recv(1024)
if not data:
break
print(str(data,'utf-8'))
if (len(sys.argv) > 1):
client=Client(sys.argv[1])
else:
server=Server()
server.run()
How can I change this code to make it work on windows 10 without such mistakes (or any other mistakes))?
Related
I'm trying to kick client from the server, and after that I get the follwing exception:
Exception in thread Thread-2 (__handle_client):
Traceback (most recent call last):
File "/Users/macbook/Desktop/Python Projects/Cars/Server/server.py", line 36, in __handle_client
message = client.recv(1024).decode(FORMAT)
OSError: [Errno 9] Bad file descriptor
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 1009, in _bootstrap_inner
self.run()
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 946, in run
self._target(*self._args, **self._kwargs)
File "/Users/macbook/Desktop/Python Projects/Cars/Server/server.py", line 41, in __handle_client
client.send('You left the chat room'.encode(FORMAT))
OSError: [Errno 9] Bad file descriptor.
But when I use the exit function it is going well. Both using the __close_connection function.
This is my Code:
def __handle_client(self,client):
while True:
try:
message = client.recv(1024).decode(FORMAT)
if self.__handle_messsage(message,client) == True:
break
except:
client.send('You left the chat room'.encode(FORMAT))
self.__broadcast(f'{self.__clientnick[client]} has left the chat room!',)
del self.__clientnick[client]
client.close()
break
def __handle_messsage(self,message,client):
if message == '/exit':
exit_message = 'You have discinnected successfully.'
self.__close_connction(exit_message,client)
return True
if message.startswith('/kick'):
if self.__clientnick.get(client) == 'admin':
for check_client in self.__clientnick:
if self.__clientnick.get(check_client) == message[6:len(message)]:
kick_message = 'You have been kicket from the chat room.'
self.__close_connction(kick_message,check_client)
return True
else:
client.send('You are not admin!'.encode(FORMAT))
def __close_connection(self,message,client):
client.send(message.encode(FORMAT))
self.__broadcast(f'{self.__clientnick[client]} has left the chat room!',client)
del self.__clientnick[client]
client.close()
It seems that you already closed the connection when you did kick and that is why you get the exception. the second exception is when you try to send a message to the closed connection.
I am using the threading module to host a web server and a Discord bot at the same time. Everything runs fine on Windows but as soon as I load it onto my Linux server I get the following error:
Starting Bot
Exception in thread Bot:
Traceback (most recent call last):
File "/usr/lib/python3.8/asyncio/unix_events.py", line 95, in add_signal_handler
signal.set_wakeup_fd(self._csock.fileno())
ValueError: set_wakeup_fd only works in main thread
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/home/webadmin/discordbot/bot/moduls/m_threadingmaker.py", line 15, in run
self.client.run(self.args[0])
File "/home/webadmin/discordbot/bot/venv/lib/python3.8/site-packages/discord/client.py", line 614, in run
loop.add_signal_handler(signal.SIGINT, lambda: loop.stop())
File "/usr/lib/python3.8/asyncio/unix_events.py", line 97, in add_signal_handler
raise RuntimeError(str(exc))
RuntimeError: set_wakeup_fd only works in main thread
I have upgraded from python 3.7 up to python 3.8 but I still have the same error.
Here is my code:
main.py (webserver worked)
dcbot = m_threadingmaker.myThread("Bot", client, secrets.token)
webserver = m_threadingmaker.myThread("Flask", app, 'localhost', '7010')
#webserver.start()
dcbot.start()
M_threadingmaker.py
from threading import Thread
class myThread (Thread):
def __init__(self, name, client, *args):
Thread.__init__(self)
self.name = name
self.client = client
self.args = args
def run(self):
print("Starting " + self.name)
if self.name == "Flask":
self.client.run(host=self.args[0], port=self.args[1])
else:
self.client.run(self.args[0])
print("Exiting " + self.name)
webserver.start()
dcbot.run()
Ok now it start the webserver and the bot. But when I try to do something after the bot start nothing happens. However, I am interested in why this is so. If someone knows a good and extensive contribution like books on threading, please send it
I'd suggest you to use client.start() in async coroutine instead of client.run() in separate thread.
More detailed example here
Minimal demonstration example:
import asyncio
async def main():
c1_reader, c1_writer = await asyncio.open_connection(host='google.com', port=80)
c1_socket = c1_writer.get_extra_info('socket')
c1_socket.close()
c2_reader, c2_writer = await asyncio.open_connection(host='google.com', port=80)
asyncio.run(main())
Running this program gives this error:
$ python3 asyncio_fd_used.py
Traceback (most recent call last):
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 469, in _sock_connect
sock.connect(address)
BlockingIOError: [Errno 36] Operation now in progress
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "asyncio_fd_used.py", line 11, in <module>
asyncio.run(main())
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 579, in run_until_complete
return future.result()
File "asyncio_fd_used.py", line 9, in main
c2_reader, c2_writer = await asyncio.open_connection(host='google.com', port=80)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/streams.py", line 77, in open_connection
lambda: protocol, host, port, **kwds)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 941, in create_connection
await self.sock_connect(sock, address)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 463, in sock_connect
self._sock_connect(fut, sock, address)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 477, in _sock_connect
self.add_writer(fd, self._sock_connect_cb, fut, sock, address)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 333, in add_writer
self._ensure_fd_no_transport(fd)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/selector_events.py", line 244, in _ensure_fd_no_transport
f'File descriptor {fd!r} is used by transport '
RuntimeError: File descriptor 8 is used by transport <_SelectorSocketTransport fd=8 read=polling write=<idle, bufsize=0>>
Just for explanation why I am doing the low-level socket.close() and not asyncio-level writer.close(): I was trying some code to send RST packet. But I can imagine other reasons why people would call socket.close(), maybe even unintentionally.
The problem is that the low-level socket is closed, but asyncio doesn't know about that and thinks it is still open. For some reason (performance?) asyncio remembers the socket file descriptor (fileno).
When a new connection is opened, operating system gives to it the same file descriptor number, and asyncio starts panicking, because it has the same exact fd number associated with that previous connection.
Solution: tell asyncio the socket is closed :)
import asyncio
async def main():
c1_reader, c1_writer = await asyncio.open_connection(host='google.com', port=80)
c1_socket = c1_writer.get_extra_info('socket')
c1_socket.close()
c1_writer.close() # <<< here
c2_reader, c2_writer = await asyncio.open_connection(host='google.com', port=80)
asyncio.run(main())
This code runs without raising an error.
What I want to do is set up an XMPP receiver using the Slixmpp library which listens for messages throughout the script execution. I think the threading library might provide a solution so tried that.
This script is for an online PvP game and I need to receive information from the opponent continuously.
This is the code I have tried:
import time
import threading as td
import slixmpp as slix
import logging
import asyncio
my_jid = "test#xmpp.jp"
my_pass = "test"
class receiver(slix.ClientXMPP):
def __init__(self, jid, password):
slix.ClientXMPP.__init__(self, jid, password)
self.add_event_handler("session_start", self.start)
self.add_event_handler("message", self.message)
def start(self, event):
self.send_presence()
self.get_roster()
def message(self, msg):
if msg['type'] in ('chat', 'normal'):
msg.reply("Thanks for sending\n%(body)s" % msg).send()
print(msg['body'])
def function():
recv = receiver(my_jid, my_pass)
recv.connect()
recv.process()
newthread = threading.Thread(target=function)
logging.basicConfig(level="DEBUG", format='%(levelname)-8s %(message)s')
newthread.start()
input("Press Enter to continue")
This returns the following error:
Exception in thread Thread-1:
Press Enter to continueTraceback (most recent call last):
File "C:\Program Files (x86)\Python37-32\lib\threading.py", line 917, in _bootstrap_inner
self.run()
File "C:\Program Files (x86)\Python37-32\lib\threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "C:/Users/dps/Documents/GitHub/Python-Problems/UltimateTicTacToe-scripts/xmppp.py", line 46, in good
recv = receiver(my_jid, my_pass)
File "C:/Users/dps/Documents/GitHub/Python-Problems/UltimateTicTacToe-scripts/xmppp.py", line 32, in __init__
slix.ClientXMPP.__init__(self, jid, password)
File "C:\Users\dps\venv\lib\site-packages\slixmpp\clientxmpp.py", line 70, in __init__
BaseXMPP.__init__(self, jid, 'jabber:client', **kwargs)
File "C:\Users\dps\venv\lib\site-packages\slixmpp\basexmpp.py", line 48, in __init__
XMLStream.__init__(self, **kwargs)
File "C:\Users\dps\venv\lib\site-packages\slixmpp\xmlstream\xmlstream.py", line 219, in __init__
self.disconnected = asyncio.Future()
File "C:\Program Files (x86)\Python37-32\lib\asyncio\events.py", line 644, in get_event_loop
% threading.current_thread().name)
RuntimeError: There is no current event loop in thread 'Thread-1'.
In my case executing:
newthread.daemon = True
Before calling:
newthread.start()
Works as expected creating a non-blocking thread.
first: I am an absolute beginner in python, I used to write PHP before, so if I am getting something complitly wrong please let me know.
I am writing an app. It should serve its information via websockets. I choosed flask-socketio for this. In the background I want to process the data. Because I would like to have the app small I decided against a solution like Celery.
I have shortened the code to:
# -*- coding: utf8 -*-
from flask import Flask, jsonify, abort, make_response, url_for, request, render_template
from flask.ext.socketio import SocketIO, emit
from multiprocessing import Pool
from multiprocessing.managers import BaseManager
import time
import os
def background_stuff(args):
while True:
try:
print args
time.sleep(1)
except Exception as e:
return e
thread = None
_pool = None
app = Flask(__name__)
app.debug = True
socketio = SocketIO(app)
#app.route('/', methods=['GET'])
def get_timers():
return 'timer'
if __name__=='__main__':
_pool = Pool(1)
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
workers = _pool.apply_async(
func=background_stuff,
args=('do background stuff',),
)
socketio.run(app)
# app.run()
When starting this, i get the following messages:
python test/multitest.py
* Running on http://127.0.0.1:5000/
* Restarting with stat
do background stuff
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 336, in _handle_tasks
for taskseq, set_length in iter(taskqueue.get, None):
File "/usr/lib/python2.7/Queue.py", line 168, in get
self.not_empty.wait()
File "/usr/lib/python2.7/threading.py", line 340, in wait
waiter.acquire()
File "gevent/_semaphore.pyx", line 112, in gevent._semaphore.Semaphore.acquire (gevent/gevent._semaphore.c:3386)
File "/home/phil/work/ttimer/server/local/lib/python2.7/site-packages/gevent/hub.py", line 338, in switch
return greenlet.switch(self)
LoopExit: This operation would block forever
do background stuff
do background stuff
do background stuff
do background stuff
do background stuff
127.0.0.1 - - [2015-09-30 00:06:23] "GET / HTTP/1.1" 200 120 0.001860
do background stuff
do background stuff
do background stuff
do background stuff
^CProcess PoolWorker-1:
Process PoolWorker-1:
Traceback (most recent call last):
Traceback (most recent call last):
File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
self.run()
self.run()
File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
self._target(*self._args, **self._kwargs)
self._target(*self._args, **self._kwargs)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 113, in worker
File "/usr/lib/python2.7/multiprocessing/pool.py", line 102, in worker
task = get()
result = (True, func(*args, **kwds))
File "/usr/lib/python2.7/multiprocessing/queues.py", line 376, in get
File "test/multitest.py", line 14, in background_stuff
KeyboardInterrupt
time.sleep(1)
KeyboardInterrupt
return recv()
KeyboardInterrupt
So the background process is working and it answers http requests (127.0.0.1 - - [2015-09-30 00:06:23] "GET / HTTP/1.1" 200 120 0.001860). But just ignoring an error because it seems to work does not seem to be a solution for me. Does anyone can tell my what I am doing wrong here?
If you say I can't do it that way can you tell me why? I would like to learn and understand what I am doing wrong.
I read something about monkepatching, but everything suggested threw just more or other errors. I think it is better to work on the first error instead of blindly trying fixes.
python -V
Python 2.7.9
Greetings
update
I added the 2 lines for monkeypatching, this is what I got:
$python multitest2.py
^CProcess PoolWorker-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 102, in worker
task = get()
File "/usr/lib/python2.7/multiprocessing/queues.py", line 376, in get
return recv()
KeyboardInterrupt
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 380, in _handle_results
task = get()
KeyboardInterrupt
* Running on http://127.0.0.1:5000/
* Restarting with stat
^CProcess PoolWorker-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 380, in _handle_results
task = get()
KeyboardInterrupt
self.run()
File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 102, in worker
task = get()
File "/usr/lib/python2.7/multiprocessing/queues.py", line 376, in get
return recv()
KeyboardInterrupt
do background stuff
FAILED to start flash policy server: [Errno 98] Address already in use: ('127.0.0.1', 10843)
$do background stuff
do background stuff
do background stuff
do background stuff
do background stuff
do background stuff
do background stuff
do background stuff
do background stuff
do background stuff
do background stuff
do background stuff
On start there is no output at all. After hittinc ctrl-c several times, i get the background stuff output. This continues until i kill the python process via SIGKILL
update 2
what I expect to see is
* Running on http://127.0.0.1:5000/
* Restarting with stat
do background stuff
do background stuff
do background stuff
right after the running of the script. But before I press ctrl-c nothing is happening.
First of all, you need to be aware that the version of Flask-SocketIO that you are using requires gevent, which is a coroutine framework. Using the asynchronous coroutines of gevent with a multiprocessing pool is a strange combination. You are using gevent, so what would make the most sense is to use the gevent pool functionality so that everything is consistent.
Now regarding the problem, I think it is likely due to not having the standard library monkey patched at an early stage. I recommend that you add the following lines at the very top of your script (above your imports, make them lines 1 and 2):
from gevent import monkey
monkey.patch_all()
These will ensure that any calls into standard library for things such as threads, semaphores, etc. go to the gevent implementations.
Update: I tried your example. The original version, without monkey-patching, works fine for me, I do not see the LoopExit error that you reported. Adding the monkey patching prevents the background processes from running, as you reported.
In any case, I converted your script to use gevent.pool and that works reliably for me. Here is the edited script:
from flask import Flask, jsonify, abort, make_response, url_for, request, render_template
from flask.ext.socketio import SocketIO, emit
from gevent.pool import Pool
import time
import os
def background_stuff(args):
while True:
try:
print args
time.sleep(1)
except Exception as e:
return e
thread = None
_pool = None
app = Flask(__name__)
app.debug = True
socketio = SocketIO(app)
#app.route('/', methods=['GET'])
def get_timers():
return 'timer'
if __name__=='__main__':
_pool = Pool(1)
workers = _pool.apply_async(
func=background_stuff,
args=('do background stuff',),
)
socketio.run(app)
Hope this helps!
I read a tutorial about gevent and fount a solution which is simple and clean for my needs:
# -*- coding: utf8 -*-
from flask import Flask
from flask.ext.socketio import SocketIO
import gevent
import os
def background_stuff():
while True:
try:
print 'doing background work ... '
gevent.sleep(1)
except Exception as e:
return e
app = Flask(__name__)
app.debug = True
socketio = SocketIO(app)
#app.route('/', methods=['GET'])
def get_timers():
return 'timer'
if __name__=='__main__':
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
gevent.spawn(background_stuff)
socketio.run(app)
The tutorial can be found here: http://sdiehl.github.io/gevent-tutorial/#long-polling
It even tells about problems with gevent and multiprocesing: http://sdiehl.github.io/gevent-tutorial/#subprocess , but because I found a simple solution fitting to my needs I didn't try anything else.