i need to use global variables in my program with either flask or bottle running as a webservice. so far im using bottle as a thread with a snippet i found here: Starting python bottle in a thread/Process and another daemon next to it
i basically want to go to localhost:8080/hello to increase the global variable test by one:
#!/usr/bin/env python
from bottle import route, run
from multiprocessing import Process
#route('/hello')
def hello():
global test
test = test + 1
return test
def main():
global test
test = 0
t = Process(target=bottle.run(host='0.0.0.0', port=8080))
t.daemon = True
t.start()
while(True)
print test
time.sleep(0.5)
if __name__ == "__main__":
main()
if i go to localhost:8080/hello with my browser i get:
Error 500: Internal Server Error - Unhandled Exception
i cant see the exception tho, even with
try
global test
test = test + 1
return test
except Exception e
print e
You're returning an int from hello, but you need to return an iterable (of strings).
Tip: add debug=True to your call to run to get better error info in your response.
t = Process(target=run(host='0.0.0.0', port=8080, debug=True))
Related
This question already has an answer here:
How to process requests from multiiple users using ML model and FastAPI?
(1 answer)
Closed 15 days ago.
I have a Python file named main.py. I am running it on Python 3.9.13 on Windows.
import uvicorn
from fastapi import FastAPI
app = FastAPI()
#app.post('/c')
async def c(b: str):
print(a)
if __name__ == '__main__':
a = load_embeddings('embeddings')
uvicorn.run('main:app', host='127.0.0.1', port=80)
Running this, then invoking POST /c will cause a 500 error with NameError 'a' is not defined.
However it is obvious that a will be defined first before the server is ran. If I move a outside of the if __name__ == '__main__': then it works, but it causes load_embeddings to be ran multiple times for unknown reasons (3 exact). Since load_embeddings for me takes long time, I do not want the duplicate execution.
I wish to look for either of these as a solution to my issue: stop whatever outside if __name__ == '__main__': from executing multiple times, OR make a defined globally when it is being defined under if __name__ == '__main__':.
Note: variable names are intentionally renamed for ease of reading. Please do not advise me anything on coding style/naming conventions. I know the community is helpful but that's not the point here, thanks.
You can resolve the issue by moving the a variable definition inside the c function. Then, you can add a check inside the function to load the embeddings only if they have not been loaded yet. You can achieve this by using a global variable, which will keep track of whether the embeddings have been loaded or not.
Here is an example:
import uvicorn
from fastapi import FastAPI
app = FastAPI()
EMBEDDINGS_LOADED = False
def load_embeddings(filename):
# Load embeddings code here
...
#app.post('/c')
async def c(b: str):
global EMBEDDINGS_LOADED
if not EMBEDDINGS_LOADED:
load_embeddings('embeddings')
EMBEDDINGS_LOADED = True
print(a)
if __name__ == '__main__':
uvicorn.run('main:app', host='127.0.0.1', port=80)
I would like to know, Is it possible to run a function after response from web.py service, which function takes long time to run?
Lets say some example as below.
file Name: code.py
import web
import time
urls = (
'/', 'index'
)
app = web.application(urls, globals())
class index:
def GET(self):
try:
with open('filename.txt', 'a') as file:
for i in range(100):
time.sleep(1)
file.write("No of times: {}".format(i))
return "some json response"
except:
return "Exception occurred"
if __name__ == "__main__":
app.run()
When I run the above code, obviously it will take time because as we are using time module for sleep one sec and then write into file. So, I should wait 100 seconds for get the response from service.
I want to skip this 100 seconds waiting time.
Expected: First return response to client and then run this part in background?
Can somebody provide some solution. Thanks..
Have a look python documentation for Thread.run()
Note:
With background task you won't be able to return "Exception occurred" as you're doing now. I believe you're OK with it.
Here's a small easy solution. There are other ways too but I feel you should explore more by yourself since you're a python beginner. :)
import web
import time
urls = (
'/', 'index'
)
app = web.application(urls, globals())
class index:
def writeToFile():
try:
with open('filename.txt', 'a') as file:
for i in range(100):
time.sleep(1)
file.write("No of times: {}".format(i))
# Log completion
except:
# Log error
def GET(self):
thread = Thread(target=writeToFile)
thread.start()
return {<myJSON>}
if __name__ == "__main__":
app.run()
When I press Ctrl+C the call jumps into signal_handler as expected, but the greenlets are not getting killed as they continue the process.
# signal handler to process after catch ctrl+c command
def signal_handler(signum, frame):
print("Inside Signal Handler")
gevent.sleep(10)
print("Signal Handler After sleep")
gevent.joinall(maingreenlet)
gevent.killall(maingreenlet,block=True,timeout=10)
gevent.kill(block=True)
sys.exit(0)
def main():
signal.signal(signal.SIGINT, signal_handler) // Catching Ctrl+C
try:
maingreenlet = [] // Creating a list of greenlets
while True:
for key,profileval in profile.items():
maingreenlet.append(gevent.spawn(key,profileval)) # appending all grrenlets to list
gevent.sleep(0)
except (Error) as e:
log.exception(e)
raise
if __name__ == "__main__":
main()
The main reason your code is not working is because the variable maingreenlet is defined inside the main function, and is out of the scope of the signal_handler function which tries to access it. Your code should throw an error like this:
NameError: global name 'maingreenlet' is not defined
If you were to move the line maingreenlet = [] into the global scope, i.e. anywhere outside of the two def blocks, the greenlets should get killed without problem.
Of course that's after you fix the other issues in your code, like using // instead of # to start the comments, or calling the function gevent.kill with the wrong parameter. (you didn't specify your gevent version but I assume the current version 1.3.7) Actually this function call is redundant after you call gevent.killall.
Learn to use a Python debugger liker pdb or rpdb2 to help you debug your code. It'll save your precious time in the long run.
I have this code where it loads necessary files and prints necessary information when the server starts but inside if __name__ == "__main__": I'm starting a background process as well then finally app.run() is executed.
My problem is after loading all and comes to the starting of background process it starts to print and load everything from beginning again. And also it does the same when the server get its first request (GET/POST). How can I make it load only once?
import web
from multiprocessing import Process
import scripts
print 'Engine Started'
# Code to load and print necessary stuff goes here...
urls = (
'/test(.*)', 'Test'
)
class Test():
def GET(self,r):
tt = web.input().t
print tt
return tt
if __name__ == "__main__":
try:
print 'Cache initializing...'
p = Process(target=scripts.initiate_cleaner)
p.start() # Starts the background process
except Exception, err:
print "Error initializing cache"
print err
app = web.application(urls, globals())
app.run()
So this loads thrice ('Engine Started' prints thrice) after starting process and requesting from localhost:8080/test?t=er
I went through this but it solves the problem in flask and I use web.py
I'm not sure why this surprises you, or why it would be a problem. A background process is by definition a separate process from the web process; each of those will import the code, and therefore print that message. If you don't want to see that message, put it inside the if __name__ block.
I'm dealing with global variables in Python. The code should work fine, but there is a problem. I have to use global variable for instance of class Back. When I run the application it says that back is None which should be not true because the second line in setup() function - 'back = Back.Back()'
# -*- coding: utf-8 -*-
from flask import Flask
from flask import request
from flask import render_template
import Search
import Back
app = Flask(__name__)
global back
back = None
#app.route('/')
def my_form():
return render_template('my-form.html')
def setup():
global back
back = Back.Back()
def is_ascii(s):
return all(ord(c) < 128 for c in s)
#app.route('/', methods=['POST'])
def search():
from time import time
pattern = request.form['text']
startTime = time()
pattern=pattern.lower()
arr = []
if len(pattern)<1:
arr.append('Incorrect input')
currentTime = time()-startTime
return render_template('my-form.html', arr=arr, time=currentTime)
arr = []
search = Search.Search(pattern,back)
results = search.getResults()
..................
return render_template('my-form.html', arr=arr, time=currentTime, pattern=pattern)
app.debug=True
if __name__ == '__main__':
setup()
app.run()
Why is the back variable None instead of instance of Back class? Thanks
The Flask development server runs your module twice. Once to run the server itself, and another time in a child process so it can reload your whole script each time you make a change to it. It is that second process that won't run the __main__ guarded code and the global is left as None.
You'll get the same problem if you used another WSGI server; it'd import your file as a module, not as the initial script and the __main__ guard is not executed.
Use a #app.before_first_request function instead; it is guaranteed to be executed when the very first request is handled for this process. This also keeps your global working if you moved to a proper WSGI container that used multiple child processes to scale your site:
#app.before_first_request
def setup():
global back
back = Back.Back()