I'm creating a platform using flask+python where each loggedin user can add several social media accounts to be used for analysis. Each account added starts a new thread with the account name, which then is saved into a dic (key=account name and value=the thread). HOWEVER, when I do a hard refresh/reload on the homepage, the dic that references all the threads gets reset and returns None. I can make modifications, like get variable values from the threads or call the kill function to end the threads.I've been looking everywhere here on this site and I can't find the solution.
I've simplified my code:
class threads_manager(threading.Thread):
def __init__(self):
super(threads_manager, self).__init__()
self.cancelled = False
self.accounts = {}
def is_loggedin(self, username):
if not self.accounts:
return self.accounts[username].logged_in()
def add_account(self, usname, uspass, PROXY):
# AddAccount runs on a seperate thread that is managed by this thread
acc = AddAccount(usname, uspass, '')
acc.start()
self.accounts.update({usname: acc})
def kill_account(self, username):
if self.accounts[username] != None:
self.accounts[username].cancel()
return True
else:
return False
def run(self):
# make sure that the thread kill it self after 1 min as I cant
#get access to it later
while not self.cancelled:
if self.timeout > 0:
time.sleep(2)
self.timeout -= 1
else:
self.cancelled = True
# create new instance as global variable
manager = threads_manager()
#app.route('/addAccounts/')
def addAccounts():
global manager
# for displaying the accounts that are already stored in the server
#shows the names of the running threads (ajax call)
if request.args.get('command') == 'GETACCOUNTS':
tnames = []
for t in threading.enumerate():
tnames.append(t.name)
# prints the names as a flash/toast
return jsonify({'success' : tname})
if request.args.get('command') == 'ADDACCOUNT':
#ajax call
manager.add_account('username', 'password', 'proxy')
else:
#when reloading the website
return render_template('addAccounts.html')
Any help, ideas?
Related
I am running a class based app using celery, but I am noting that when two processes run simultaneously, certain staticmethods in the class are not acting independently. Here is the app invocation
import os
from PriceOptimization.celery import app
from .Tasks_Sim.sim import Sim, final_report
#app.task(name='Simulations.tasks.scoring')
def simulation(clients, deciles):
s = Sim(**sim_params)
market_by_year = s.control_flow(my_save_path)
report = final_report(market_by_year)
return report
Within my Sim app, I have a class method that creates id's for my instance as follows
class Company:
company_id = 0
#classmethod
def set_company_no(cls):
cls.company_id += 1
return cls.company_id-1
def __init__(self, companies, year):
self._company_id = Company.set_company_no()
self._company_year = year
Usually the first task instantiated will complete successfully, but on the next invocation, I am getting a list index out of range error that suggests to me that my workers are not independent and that my company_id object is not commencing from zero with the next invocation. How can I prevent this side effect and have each app run independently?
For now, I have elected to make my process run sequentially using a redis lock:
from settings import REDIS_INSTANCE
REDIS_LOCK_KEY = 'ABC'
#app.task(name='Simulations.tasks.scoring')
def simulation(clients, deciles):
timeout = (60 * 5)
have_lock = False
my_lock = REDIS_INSTANCE.lock(REDIS_LOCK_KEY, timeout=timeout)
while have_lock == False:
have_lock = my_lock.acquire(blocking=False)
if have_lock:
print('unique process commencing...')
s = Sim(**sim_params)
market_by_year = s.control_flow(my_save_path)
report = final_report(market_by_year)
else:
print('waiting for lock to commence...')
time.sleep(10)
my_lock.release()
return report
I have a class showAllThreads that monitors all the existing threads in the script (music player)
class showAllThreads(threading.Thread):
def __init__(self, *args, **kwargs):
threading.Thread.__init__(self, *args, **kwargs)
self.daemon = True
self.start()
#Shows whether the playing music is in queue, initially false
musicQueue = False
def run(self):
while True:
allThreads = threading.enumerate()
for i in allThreads:
if i.name == "PlayMusic" and i.queue == True:
musicQueue = True
print("Playlist is on")
elif i.name == "PlayMusic" and i.queue == False:
musicQueue = False
print("Playlist is off")
else:
musicQueue = False
time.sleep(2)
When I try to access musicQueue from the mainthread by allThreads.musicQueue where allThreads = showAllThreads()it always gives me value False, even though the while loop executes musicQueue = True. I know that the playlist is on, because the print command excecutes successfully.
You define "musicQueue" in two places: first at the class-level (which makes it a class attribute - an attribute that is shared between all instances of the class), then as a local variable in the run() method. These are two totally distinct names, so you can't expect assigning to the local variable to change the class-level one in any way.
I assume you're new to Python and didn't take time to learn how it's object model works and how it differs from most mainstream OOPLs. You really should if you hope to enjoy coding in Python...
What you want here is obviously to make musicQueue an instance variable and assign to it within run():
class ShowAllThreads(threading.Thread):
def __init__(self, *args, **kwargs):
threading.Thread.__init__(self, *args, **kwargs)
self.daemon = True
# create an instance variable
self.musicQueue = False
self.start()
def run(self):
while True:
allThreads = threading.enumerate()
for i in allThreads:
if i.name == "PlayMusic" and i.queue == True:
# rebind the instance variable
self.musicQueue = True
print("Playlist is on")
elif i.name == "PlayMusic" and i.queue == False:
self.musicQueue = False
print("Playlist is off")
else:
self.musicQueue = False
time.sleep(2)
I am trying to build a coap server, in which I can add a new resource without the need to stop the server, recode it and restart .my server is suppossed to host two types of resources, "sensors(Sens-Me)" and "Actuators(Act-Me)" . I want that if I press the A key, a new instance of actuator should be added to the server, likewise If i Press S for Sensor .Below is my code :
from coapthon.resources.resource import Resource
from coapthon.server.coap import CoAP
class Sensor(Resource):
def __init__(self,name="Sensor",coap_server=None):
super(Sensor,self).__init__(name,coap_server,visible=True,observable=True,allow_children=True)
self.payload = "This is a new sensor"
self.resource_type = "rt1"
self.content_type = "application/json"
self.interface_type = "if1"
self.var = 0
def render_GET(self,request):
self.payload = "new sensor value ::{}".format(str(int(self.var+1)))
self.var +=1
return self
class Actuator(Resource):
def __init__(self,name="Actuator",coap_server=None):
super(Actuator,self).__init__(name,coap_server,visible=True,observable=True)
self.payload="This is an actuator"
self.resource_type="rt1"
def render_GET(self,request):
return self
class CoAPServer(CoAP):
def __init__(self, host, port, multicast=False):
CoAP.__init__(self,(host,port),multicast)
self.add_resource('sens-Me/',Sensor())
self.add_resource('act-Me/',Actuator())
print "CoAP server started on {}:{}".format(str(host),str(port))
print self.root.dump()
def main():
ip = "0.0.0.0"
port = 5683
multicast=False
server = CoAPServer(ip,port,multicast)
try:
server.listen(10)
print "executed after listen"
except KeyboardInterrupt:
server.close()
if __name__=="__main__":
main()
I am not sure what exactly do you want to do.
Is it just to replace a resource on the same route or add a new one?
Replace a resource
It is not possible according to the current coapthon version source:
https://github.com/Tanganelli/CoAPthon/blob/b6983fbf48399bc5687656be55ac5b9cce4f4718/coapthon/server/coap.py#L279
try:
res = self.root[actual_path]
except KeyError:
res = None
if res is None:
if len(paths) != i:
return False
resource.path = actual_path
self.root[actual_path] = resource
Alternatively, you can solve it in scope of request.
Say, have a registry of handlers which are used by resources and can be changed on a user input event. Well, you'll not be able to add new routes.
If you absolutely need that feature, you may request it from a developer or contribute to that project.
Add a new resource
I have extended your snippet a little bit.
I have a little experience in Python so I an not sure I've made everything properly, but it works.
There is a separate thread polling the user input and adding the same resource. Add the needed code there.
from coapthon.resources.resource import Resource
from coapthon.server.coap import CoAP
from threading import Thread
import sys
class Sensor(Resource):
def __init__(self,name="Sensor",coap_server=None):
super(Sensor,self).__init__(name,coap_server,visible=True,observable=True,allow_children=True)
self.payload = "This is a new sensor"
self.resource_type = "rt1"
self.content_type = "application/json"
self.interface_type = "if1"
self.var = 0
def render_GET(self,request):
self.payload = "new sensor value ::{}".format(str(int(self.var+1)))
self.var +=1
return self
class Actuator(Resource):
def __init__(self,name="Actuator",coap_server=None):
super(Actuator,self).__init__(name,coap_server,visible=True,observable=True)
self.payload="This is an actuator"
self.resource_type="rt1"
def render_GET(self,request):
return self
class CoAPServer(CoAP):
def __init__(self, host, port, multicast=False):
CoAP.__init__(self,(host,port),multicast)
self.add_resource('sens-Me/',Sensor())
self.add_resource('act-Me/',Actuator())
print "CoAP server started on {}:{}".format(str(host),str(port))
print self.root.dump()
def pollUserInput(server):
while 1:
user_input = raw_input("Some input please: ")
print user_input
server.add_resource('sens-Me2/', Sensor())
def main():
ip = "0.0.0.0"
port = 5683
multicast=False
server = CoAPServer(ip,port,multicast)
thread = Thread(target = pollUserInput, args=(server,))
thread.setDaemon(True)
thread.start()
try:
server.listen(10)
print "executed after listen"
except KeyboardInterrupt:
print server.root.dump()
server.close()
sys.exit()
if __name__=="__main__":
main()
In a previous question, the issue was how to implement a conditional loop (a simple for loop) to affect the onMessage event calling function, which was resolved. However, my current issue is in trying to implement time as the determinant in the conditional loop.
Currently, the code runs but only seems to do the while loop that rechecks the time, ignoring the code before it. I suspect that the issue is in the location that I have placed the time rechecking loop?
Any clarity on this issue would be appreciated!
import ch
import time
class bot(ch.RoomManager):
timeleft = 0
starttime = 0
def onMessage(self, room, user, message):
print("[{0}] {1}: {2}".format(room.name, user.name.title(), message.body))
if 100 >= timeleft >= 1:
print('success')
else:
print('fail')
loop = 1
while loop == 1 :
timeleft = starttime - int(time.clock())
if timeleft <=0:
timeleft = 200
starttime = 200
rooms = ["testgroup444"]
username = "user"
password = "name"
bot.easy_start(rooms,username,password)
For clarity on the methods used, the entire ch.py library can be found here: https://pastebin.com/8ukS4VR1
I think you still have an issue with the Python syntax. In Python whitespace is very important as it defines scope. The way your code is written, the while loop is executed at the time the class is defined, before anything is started.
Further, the code gets into an infinite loop, as while loop == 1 will be always True. This is why you see that your code gets stuck. From the discussion in the comments, I imagine you want to write something like:
import ch
import time
import enum
class State(enum.Enum):
idle = 0
nominating = 1
voting = 2
watching = 3
class bot(ch.RoomManager):
state = State.idle
movie_length = 20
def updateState(self):
if self.state in [State.idle, State.nominating]:
self.state = State.voting
timeout = 10
elif self.state == voting:
self.state = State.watching
timeout = self.movie_length - 15
else: # if self.state == watching
self.state = State.nominating
timeout = 15
self.setTimeout(timeout*60, bot.updateState, self)
def onConnect(self, room):
# Redirect through event loop, not strictly nessecary
self.setTimeout(0, bot.updateState, self)
def onMessage(self, room, user, message):
print("[{0}] {1}: {2}".format(room.name, user.name.title(), message.body))
print("Current state is {0}".format(self.state))
rooms = ["testgroup444"]
username = "user"
password = "name"
bot.easy_start(rooms,username,password)
Here, the setTimeout method defined in the ch (bot) class is used, to allow messages to be passed at certain times. At every timeout the state is updated. The actual state is then available in all internal methods, e.g. in onMessage and updateState.
As I do not use the chat network or client I cannot guarantee that the solution works, though.
I want to convert my current tornado app from using #web.asynchronous to #gen.coroutine. My asynchronous callback is called when a particular variable change happens on an IOLoop iteration. The current example in Tornado docs solves an I/O problem but in my case its the variable that I am interested in. I want the coroutine to wake up on the variable change. My app looks like the code shown below.
Note: I can only use Python2.
# A transaction is a DB change that can happen
# from another process
class Transaction:
def __init__(self):
self.status = 'INCOMPLETE'
self.callback = None
# In this, I am checking the status of the DB
# before responding to the GET request
class MainHandler(web.RequestHandler):
def initialize(self, app_reference):
self.app_reference = app_reference
#web.asynchronous
def get(self):
txn = Transaction()
callback = functools.partial(self.do_something)
txn.callback = callback
self.app_reference.monitor_transaction(txn)
def do_something(self):
self.write("Finished GET request")
self.finish()
# MyApp monitors a list of transactions and adds the callback
# 'transaction.callback' when transactions status changes to
# COMPLETE state.
class MyApp(Application):
def __init__(self, settings):
self.settings = settings
self._url_patterns = self._get_url_patterns()
self.txn_list = [] # list of all transactions being monitored
Application.__init__(self, self._url_patterns, **self.settings)
IOLoop.current().add_callback(self.check_status)
def monitor_transaction(self, txn):
self.txn_list.append(txn)
def check_status(self):
count = 0
for transaction in self.txn_list:
transaction.status = is_transaction_complete()
if transaction.status is 'COMPLETE':
IOLoop.current().add_callback(transaction.callback)
self.txn_list.pop(count)
count += 1
if len(self.txn_list):
IOloop.current().add_callback(self.check_status)
# adds 'self' to url_patterns
def _get_url_patterns(self):
from urls import url_patterns
modified_url_patterns = []
for url in url_patterns:
modified_url_patterns.append( url + ({ 'app_reference': self },))
return modified_url_patterns
If I understand right for it to write using gen.coroutine the get should be modified as
#gen.coroutine
def get(self):
txn = Transaction()
response = yield wake_up_when_transaction_completes()
# respond to GET here
My issue is I am not sure how to wake a routine only when the status changes and I cannot use a loop as it will block the tornado thread. Basically I want to notify from the IOLoop iteration.
def check_status():
for transaction in txn_list:
if transaction.status is 'COMPLETE':
NOTIFY_COROUTINE
Sounds like a job for the new tornado.locks! Released last week with Tornado 4.2:
http://tornado.readthedocs.org/en/latest/releases/v4.2.0.html#new-modules-tornado-locks-and-tornado-queues
Use an Event for this:
from tornado import locks, gen
event = locks.Event()
#gen.coroutine
def waiter():
print("Waiting for event")
yield event.wait()
print("Done")
#gen.coroutine
def setter():
print("About to set the event")
event.set()
More info on the Event interface:
http://tornado.readthedocs.org/en/latest/locks.html#tornado.locks.Event