I'm trying to control a robot with ROS and flask. The problem is that when i kill ROS with ctrl-c (SIGINT) flask is slowing this process down because it is not closing right away. I have implemented a signal_handler to handle the ctrl-c and close flask.
The problem is that when i run this and press
ctrl-c i closes everything right away but i get the following error:
RuntimeError: Working outside of request context.
How can i fix this error?
#!/usr/bin/env python
import rospy
from raspimouse_ros.msg import MotorFreqs
from time import sleep
from flask import Flask, request
from os.path import join, dirname
from signal import signal, SIGINT
cwd = dirname(__file__)
open(join(cwd, "file.html"))
app = Flask(__name__)
deltaX = 0
deltaY = 0
pub = rospy.Publisher('/motor_raw', MotorFreqs, queue_size=10)
rospy.init_node('control')
msg = MotorFreqs()
def signal_handler(signal_received, frame):
msg.left = 0
msg.right = 0
pub.publish(msg)
print("Quitting .......")
func = request.environ.get('werkzeug.server.shutdown')
func()
signal(SIGINT,signal_handler)
#app.route("/")
def main():
with open(join(cwd, "file.html"), 'r') as f:
program = f.read()
return program
#app.route("/SetSpeed")
def SetSpeed():
global deltaX
global deltaY
deltaX = int(float(request.args.get('x')) * 4)
deltaY = int(float(request.args.get('y')) * 10)
publisher()
return ""
def publisher():
msg.left = int(-deltaY+deltaX)
msg.right = int(-deltaY-deltaX)
rospy.loginfo(msg)
pub.publish(msg)
app.run(host="0.0.0.0")
[control-1] killing on exit
Quitting .......
Traceback (most recent call last):
File "/home/pi/workspace/src/manual_control/scripts/control.py", line 54, in <module>
app.run(host="0.0.0.0")
File "/usr/lib/python2.7/dist-packages/flask/app.py", line 841, in run
run_simple(host, port, self, **options)
File "/usr/lib/python2.7/dist-packages/werkzeug/serving.py", line 708, in run_simple
inner()
File "/usr/lib/python2.7/dist-packages/werkzeug/serving.py", line 673, in inner
srv.serve_forever()
File "/usr/lib/python2.7/dist-packages/werkzeug/serving.py", line 511, in serve_forever
HTTPServer.serve_forever(self)
File "/usr/lib/python2.7/SocketServer.py", line 231, in serve_forever
poll_interval)
File "/usr/lib/python2.7/SocketServer.py", line 150, in _eintr_retry
return func(*args)
File "/home/pi/workspace/src/manual_control/scripts/control.py", line 28, in signal_handler
func = request.environ.get('werkzeug.server.shutdown')
File "/usr/lib/python2.7/dist-packages/werkzeug/local.py", line 343, in __getattr__
return getattr(self._get_current_object(), name)
File "/usr/lib/python2.7/dist-packages/werkzeug/local.py", line 302, in _get_current_object
return self.__local()
File "/usr/lib/python2.7/dist-packages/flask/globals.py", line 37, in _lookup_req_object
raise RuntimeError(_request_ctx_err_msg)
RuntimeError: Working outside of request context.
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem.
shutting down processing monitor...
... shutting down processing monitor complete
done
The request context is active when a request arrives and is destroyed after it finishes, so it is not availale in the signal_handler function, you can, however, access app_context.
Related
I am trying to run a discord bot and flask server in one file, I thought it worked but the flask server does nothing so I checked with debug options True, now I get this error:
$ python main.py
Traceback (most recent call last):
File "main.py", line 262, in <module>
run()
File "main.py", line 260, in run
* Serving Flask app 'main'
* Debug mode: on
Tools().discordbot()
File "main.py", line 204, in discordbot
threading.Thread(target=loopy.run_forever).start()
NameError: name 'loopy' is not defined
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:8080
* Running on http://198.54.114.12:8080
Press CTRL+C to quit
Exception in thread Thread-1:
Traceback (most recent call last):
File "/opt/alt/python38/lib64/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/opt/alt/python38/lib64/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "main.py", line 213, in __init__
self.RunApi()
File "main.py", line 254, in RunApi
app.run(host="0.0.0.0",port=8080, debug=True)
File "/home/darkehld/virtualenv/verify.darkys.wtf/3.8/lib/python3.8/site-packages/flask/app.py", line 1188, in run
run_simple(t.cast(str, host), port, self, **options)
File "/home/darkehld/virtualenv/verify.darkys.wtf/3.8/lib/python3.8/site-packages/werkzeug/serving.py", line 1090, in run_simple
run_with_reloader(
File "/home/darkehld/virtualenv/verify.darkys.wtf/3.8/lib/python3.8/site-packages/werkzeug/_reloader.py", line 427, in run_with_reloader
signal.signal(signal.SIGTERM, lambda *args: sys.exit(0))
File "/opt/alt/python38/lib64/python3.8/signal.py", line 47, in signal
handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
ValueError: signal only works in main thread
my contains this to start the discord bot which works fine:
myLoop.start()
threading.Thread(target=loopy.run_forever).start()
loop = asyncio.get_event_loop()
loop.create_task(self.bot.start(self.BotToken))
threading.Thread(target=loop.run_forever).start()
but the flask server does not work, the run command I use for it is this:
class ApiBot:
def __init__(self) -> None:
self.RunApi()
def RunApi(self):
app = Flask(__name__)
#app.route('/auth')
def auth():
code = request.args.get("code")
if (code != None):
if AntiSql(code) == True:
return jsonify({"error":"1004"})
discord = Discordx()
res = discord.ExchangeCode(code)
try:
access_token = res['access_token']
refresh_token = res['refresh_token']
info = discord.GetInfo(access_token)
username = info['username']
avatar = info['avatar']
userid = info['id']
except:
return jsonify({"error":"1005"})
data = {
"access_token": access_token,
"refresh_token": refresh_token,
"username":username,
"avatar":avatar,
"userid":userid,
"ip":request.remote_addr
}
if Memberdb.CheckIfUserIsInDb(data) == False:
Memberdb.AddNewMember(data)
ListToSend.append(data)
return "<script>window.close();</script>"
else:
return jsonify({"error":"1002"})
app.run(host="0.0.0.0",port=8080, debug=True)
def run():
threading.Thread(target=ApiBot).start()
can someone help me? thanks in advance
I have long running file I/O tasks which I'd like to be able to move into a daemon/server process. A CLI tool would be used to queue new jobs to run, query the status of running jobs, and wait for individual jobs. Python's multiprocessing.managers looks like a nice simple way to handle the IPC. I'd like to be able to construct a SyncManager.Event for the client to wait on without blocking the server, but attempting to do so results in triggers a "server not yet started" assertion. Ironically this assertion gets sent from the server to the client, so obviously the server is started, somewhere.
Here's the minimal example:
#!/usr/bin/env python3
import time
import sys
import concurrent.futures
from multiprocessing.managers import SyncManager
def do_work(files):
"""Simulate doing some work on a set of files."""
print(f"Starting work for {files}.")
time.sleep(2)
print(f"Finished work for {files}.")
# Thread pool to do work in.
pool = concurrent.futures.ProcessPoolExecutor(max_workers=1)
class Job:
job_counter = 1
def __init__(self, files):
"""Setup a job and queue work for files on our thread pool."""
self._job_number = self.job_counter
Job.job_counter += 1
print(f"manager._state.value = {manager._state.value}")
self._finished_event = manager.Event()
print(f"Queued job {self.number()}.")
future = pool.submit(do_work, files)
future.add_done_callback(lambda f : self._finished_event.set())
def number(self):
return self._job_number
def event(self):
"""Get an event which can be waited on for the job to complete."""
return self._finished_event
class MyManager(SyncManager):
pass
MyManager.register("Job", Job)
manager = MyManager(address=("localhost", 16000), authkey=b"qca-authkey")
if len(sys.argv) > 1 and sys.argv[1] == "server":
manager.start()
print(f"Manager listening at {manager.address}.")
while True:
time.sleep(1)
else:
manager.connect()
print(f"Connected to {manager.address}.")
job = manager.Job(["a", "b", "c"])
job.event().wait()
print("Done")
If I run the client I see:
$ ./mp-manager.py
Connected to ('localhost', 16000).
Traceback (most recent call last):
File "./mp-manager.py", line 54, in <module>
job = manager.Job(["a", "b", "c"])
File "/usr/lib/python3.8/multiprocessing/managers.py", line 740, in temp
token, exp = self._create(typeid, *args, **kwds)
File "/usr/lib/python3.8/multiprocessing/managers.py", line 625, in _create
id, exposed = dispatch(conn, None, 'create', (typeid,)+args, kwds)
File "/usr/lib/python3.8/multiprocessing/managers.py", line 91, in dispatch
raise convert_to_error(kind, result)
multiprocessing.managers.RemoteError:
---------------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.8/multiprocessing/managers.py", line 210, in handle_request
result = func(c, *args, **kwds)
File "/usr/lib/python3.8/multiprocessing/managers.py", line 403, in create
obj = callable(*args, **kwds)
File "./mp-manager.py", line 24, in __init__
self._finished_event = manager.Event()
File "/usr/lib/python3.8/multiprocessing/managers.py", line 740, in temp
token, exp = self._create(typeid, *args, **kwds)
File "/usr/lib/python3.8/multiprocessing/managers.py", line 622, in _create
assert self._state.value == State.STARTED, 'server not yet started'
AssertionError: server not yet started
---------------------------------------------------------------------------
The server output is:
$ ./mp-manager.py server
Manager listening at ('127.0.0.1', 16000).
manager._state.value = 0
I'm trying to write a simple server that disconnects a user after a min of inactivity.
ive found a simple way of doing it with threading.Timer (restarting the timer every time there is an activity).
im getting RuntimeError when using disconnect in a Timer.
tried using app.app_context and app.test_request_context but either I don't know how and where to use them or it simply doesn't work.
server code:
from flask import Flask, request
from flask_socketio import SocketIO, emit, disconnect
from threading import Timer
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
sio = SocketIO(app)
clients = {}
class Client:
def __init__(self, user, sid, client_time):
self.user = user
self.sid = sid
self.client_time = client_time
self.activity_timer = Timer(10, self.disc_after_60)
self.start_timer()
def disc_after_60(self):
disconnect(self.sid)
del clients[self.user]
def start_timer(self):
if self.activity_timer.is_alive():
self.activity_timer.cancel()
self.activity_timer.start()
else:
self.activity_timer.start()
#sio.on('register')
def handle_register(client_user, client_time):
clients[client_user] = Client(client_user, request.sid, client_time)
emit('message', ("SERVER", f"{client_user} has joined the server!"), broadcast=True)
client side I just connect using register.
the full error message:
Exception in thread Thread-8:
Traceback (most recent call last):
File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 1254, in run
self.function(*self.args, **self.kwargs)
File "C:\Users\idshi\PycharmProjects\PyChat excersize\Server\fsserver.py", line 24, in disc_after_60
disconnect(self.sid)
File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\site-packages\flask_socketio\__init__.py", line 919, in disconnect
socketio = flask.current_app.extensions['socketio']
File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\site-packages\werkzeug\local.py", line 348, in __getattr__
return getattr(self._get_current_object(), name)
File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\site-packages\werkzeug\local.py", line 307, in _get_current_object
return self.__local()
File "C:\Users\idshi\AppData\Local\Programs\Python\Python38-32\lib\site-packages\flask\globals.py", line 52, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context(). See the
documentation for more information.
I would be glad if someone can help me with this. Thanks in advance.
The disconnect() function needs to be called with an application context installed, as that's the only way to know what's the application instance.
Try this:
def disc_after_60(self):
with app.app_context():
disconnect(sid=self.sid, namespace='/')
del clients[self.user]
I use celery 4.3.0 and rabbitmq 3.6.6. There is also a Haproxy for balancing rabbitmq, but right now it only uses one rabbitmq node.
Timeout client/server in Haproxy 24 hours.
Sometimes I get an error and the task execution status is not returned, while the tasks continue to run:
Received 0x00 while expecting 0xce
Traceback (most recent call last):
File "/var/www/serv/app/mod_axmsg/dispatch.py", line 376, in execute
result_value = func_meta.func(*task.args_list, **task.kwargs_dict)
File "/var/www/serv/app/mod_rmc/libs/health.py", line 91, in update_all_health
health.update_all_health()
File "/var/www/serv/app/mod_core/libs/health.py", line 515, in update_all_health
result.join()
File "/usr/local/serv/lib/python3.5/site-packages/celery/result.py", line 765, in join
interval=interval, no_ack=no_ack, on_interval=on_interval,
File "/usr/local/serv/lib/python3.5/site-packages/celery/result.py", line 226, in get
on_message=on_message,
File "/usr/local/serv/lib/python3.5/site-packages/celery/backends/asynchronous.py", line 188, in wait_for_pending
for _ in self._wait_for_pending(result, **kwargs):
File "/usr/local/serv/lib/python3.5/site-packages/celery/backends/asynchronous.py", line 255, in _wait_for_pending
on_interval=on_interval):
File "/usr/local/serv/lib/python3.5/site-packages/celery/backends/asynchronous.py", line 56, in drain_events_until
yield self.wait_for(p, wait, timeout=1)
File "/usr/local/serv/lib/python3.5/site-packages/celery/backends/asynchronous.py", line 65, in wait_for
wait(timeout=timeout)
File "/usr/local/serv/lib/python3.5/site-packages/celery/backends/rpc.py", line 63, in drain_events
return self._connection.drain_events(timeout=timeout)
File "/usr/local/serv/lib/python3.5/site-packages/kombu/connection.py", line 323, in drain_events
return self.transport.drain_events(self.connection, **kwargs)
File "/usr/local/serv/lib/python3.5/site-packages/kombu/transport/pyamqp.py", line 103, in drain_events
return connection.drain_events(**kwargs)
File "/usr/local/serv/lib/python3.5/site-packages/amqp/connection.py", line 505, in drain_events
while not self.blocking_read(timeout):
File "/usr/local/serv/lib/python3.5/site-packages/amqp/connection.py", line 510, in blocking_read
frame = self.transport.read_frame()
File "/usr/local/serv/lib/python3.5/site-packages/amqp/transport.py", line 280, in read_frame
'Received {0:#04x} while expecting 0xce'.format(ch))
amqp.exceptions.UnexpectedFrame: Received 0x00 while expecting 0xce
My code: celery.py
import logging
from app import db
from celery import Celery
LOG = logging.getLogger(__name__)
def make_celery(flask_app):
broker = flask_app.config['AMQP_URL']
celery = Celery('mod_celery', broker=broker, backend="rpc://")
celery.conf.update(flask_app.config)
class ContextTask(celery.Task):
def __call__(self, *args, **kwargs):
with flask_app.app_context():
return self.run(*args, **kwargs)
celery.Task = ContextTask
return celery
def in_tx(task_function):
def tx_wrapper(*args):
try:
task_function(*args)
db.session.commit()
except Exception as ex:
msg = 'Could not execute task {}. Reason: {}.' \
.format(task_function.__name__, str(ex))
LOG.error(msg)
db.session.rollback()
return tx_wrapper
And file tasks.py
from app import celery
from .celery import in_tx
#celery.task(name='app.mod_celery.update_client_health_task')
#in_tx
def update_client_health_task(client_id):
from app.mod_core.libs.health import update_client_health
update_client_health(client_id)
What could be the problem? Please don't offer me redis.
I'm not a developer and I didn't write it the code, but I really need to figure it out. I'm new to python
Thanks.
I'm trying to run two servers using web.py and initiating calls from one to another. Both servers start normally but when I try to call a url the below stack trace is thrown.
import web
urls = (
'/ping', 'Ping',
'/acqlock/+(.*)', 'Acquire',
)
class MSA(web.application):
def run(self, port=8081, *middleware):
func = self.wsgifunc(*middleware)
return web.httpserver.runsimple(func, ('127.0.0.1', port))
app = MSA(urls, globals())
if __name__ == "__main__":
app.run(port=8081)
class Acquire:
def GET(self, resource_name):
print resource_name
response = app.request('http://127.0.0.1:8080/acqlock/' + resource_name, method='GET')
return response
But I keep getting this error after calling the /acqlock.
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\web\wsgiserver\__init__.py", line 1245, in communicate
req.respond()
File "C:\Python27\lib\site-packages\web\wsgiserver\__init__.py", line 775, in respond
self.server.gateway(self).respond()
File "C:\Python27\lib\site-packages\web\wsgiserver\__init__.py", line 2018, in respond
response = self.req.server.wsgi_app(self.env, self.start_response)
File "C:\Python27\lib\site-packages\web\httpserver.py", line 306, in __call__
return self.app(environ, xstart_response)
File "C:\Python27\lib\site-packages\web\httpserver.py", line 274, in __call__
return self.app(environ, start_response)
File "C:\Python27\lib\site-packages\web\application.py", line 279, in wsgi
result = self.handle_with_processors()
File "C:\Python27\lib\site-packages\web\application.py", line 249, in handle_with_processors
return process(self.processors)
File "C:\Python27\lib\site-packages\web\application.py", line 246, in process
raise self.internalerror()
File "C:\Python27\lib\site-packages\web\application.py", line 515, in internalerror
parent = self.get_parent_app()
File "C:\Python27\lib\site-packages\web\application.py", line 500, in get_parent_app
if self in web.ctx.app_stack:
AttributeError: 'ThreadedDict' object has no attribute 'app_stack'
Use requests library for this.
import requests
response = requests.request(method='GET', url ='http://127.0.0.1:8080/acqlock/' + resource_name)
Note: You have used port 8080 in url even though you have hosted the web.py in 8081