I wrote a Python script to show a desktop notification if the price of bitcoin reaches $4,500, but the script will quit if the price is reached. How do I keep the script running?
Here is the code:
import time
import requests
import gi
gi.require_version('Notify', '0.7')
from gi.repository import Notify
r = requests.get("https://api.coindesk.com/v1/bpi/currentprice.json")
r.json()
resp = r.json()
price = resp["bpi"]["USD"]["rate_float"]
top = 4200
if price > top :
# One time initialization of libnotify
Notify.init("Crypto Notify")
# Create the notification object
summary = "Crypto Alert!"
body = "BTC : $ %s" % (price)
notification = Notify.Notification.new(
summary,
body, # Optional
)
# Actually show on screen
notification.show()
else:
while price < top :
r =requests.get("https://api.coindesk.com/v1/bpi/currentprice.json")
print price
time.sleep(10)
So from what I see it seems that you scripts is written to execute in a single pass i.e. all statements will be excuted only once. So what is happening is your script waits for the condition of price greater then to be true and once it is true it executes the rest of script of IF block.
What you need is an loop that encapsulates the script and who's end condition will take long time to achieve kind of infinite loop but safer.
Also another approach you may try is keep the script in infinite loop and simply exit the script when you want using ctrl + c
Although its not very clean way to do it.
Sample code :
import time
import requests
import gi
gi.require_version('Notify', '0.7')
from gi.repository import Notify
while true :
r = requests.get("https://api.coindesk.com/v1/bpi/currentprice.json")
r.json()
resp = r.json()
price = resp["bpi"]["USD"]["rate_float"]
top = 4200
if price > top :
# One time initialization of libnotify
Notify.init("Crypto Notify")
# Create the notification object
summary = "Crypto Alert!"
body = "BTC : $ %s" % (price)
notification = Notify.Notification.new(summary,body)
# Actually show on screen
notification.show()
else:
r =requests.get("https://api.coindesk.com/v1/bpi/currentprice.json")
print price
time.sleep(10)
Related
I wanted to make a notification system for StackOverflow using tkinter, when an item is unread in my inbox i want it to show the notification(but only once), which it does. But its not efficient. In some ways it shows notification once, and when i click on it, it takes some time for the notification to be identified as read by the API, So new notifications keeps on popping up, causing GUI to crash(as im running it inside of a after()). So i wanted to know if the notification part could be made more efficient in some way.
Code:
import tkinter as tk
import add
from time import ctime
import datetime
from stackapi import StackAPI
from win10toast import ToastNotifier
import threading
import webbrowser
root = tk.Tk()
root.title('Stack Notifier')
def authorise():
print('auth')
global end, acc_key, start, inbox, auth_button
if required:
add.run() #selenium for automation
acc_key = add.acc_key_dum #accesskey passed from another module
start = datetime.datetime.now()
hours_added = datetime.timedelta(hours=24)
end = start + hours_added #time for reaunthentication
site.key = add.key #access key from another module
site.access_token = acc_key #access token from another module
site.max_pages = 1
inbox = site.fetch('users/13382000/inbox')
auth_button['state'] = tk.DISABLED
threading.Thread(target=first).start()
else:
inbox = site.fetch('users/13382000/inbox')
threading.Thread(target=first).start()
def first():
global current, required, inbox, auth_button
def popup():
webbrowser.open(link,new=0)
inbox = site.fetch('users/13382000/inbox')
print('chc')
current = datetime.datetime.now()
if start < current < end:
required = False
else:
required = True
auth_button['state'] = tk.NORMAL
if not required:
print('first')
is_unread = inbox['items'][0]['is_unread']
if is_unread:
title = inbox['items'][0]['title']
item_type = inbox['items'][0]['item_type']
link = inbox['items'][0]['link']
creation_date = ctime(inbox['items'][0]['creation_date'])
noti = ToastNotifier()
noti.show_toast(f'StackOveflow - {item_type}',f'{title} - {creation_date}',duration=5,callback_on_click=popup,threaded=True)
print('yes')
else:
threading.Thread(target=authorise).start()
root.after(1000,threading.Thread(target=first).start)
required = True #a reference to whether authentication is required again, after 24 hrs
label_login = tk.Label(root,text='Click To authorise with StackOverflow',font=('helvatica',16))
label_login.grid(row=0,columnspan=3)
auth_button = tk.Button(root,text='Authorise',command=authorise)
auth_button.grid(row=1,column=1)
site = StackAPI('stackoverflow')
root.mainloop()
I know this is not the best of codes, but im open to ideas and suggestions.
PS: Im using selenium for automation and ask for user credentials. and it requires giving permission every 24 hours, so i need to boot up selenium every 24 hours too, which is being finely done, i guess.
Thanks in advance :D
from arcgis.gis import GIS
from IPython.display import display
gis = GIS("portal url", 'username', 'password')
#search for the feature layer named Ports along west coast
search_result = gis.content.search('title:Ports along west coast')
#access the item's feature layers
ports_item = search_result[0]
ports_layers = ports_item.layers
#query all the features and display it on a map
ports_fset = ports_layers[0].query() #an empty query string will return all
ports_flayer = ports_layers[0]
ports_features = ports_fset.features
# select San Francisco feature
sfo_feature = [f for f in ports_features if f.attributes['port_name']=='SAN FRANCISCO'][0]
sfo_feature.attributes
try:
update_result = ports_flayer.edit_features(updates=[sfo_edit])
except:
pass
This is the example that I have shown in which I am trying to update feature layer. Actually I am updating the records in a loop so there are many records. The problem is in the case "Internet Connection" is just shot down It get stuck to the function edit_features.
So there is no way It could go to except and continue the flow.
I just have to ctrl+c to stop script execution because it got hanged and edit_features() function. What can I do?
If I am in your situation i would search arcgis API docs for setting connection timeout, if you can't find any i suggest:
use threading module to run update function in separate thread, it is not the efficient way but in case if it gets stuck, you can continue running your remaining code.
use python requests library to check any website and you check for response code before making the update.
code for threading will look like:
from threading import Thread
from time import sleep
def update():
global update_result
update_result = ports_flayer.edit_features(updates=[sfo_edit])
try:
update_result = None
t1 = Thread(target=update)
t1.daemon = True # mark our thread as a daemon
t1.start()
sleep(10) # wait 10 seconds then timeout, adjust according to your needs
if update_result == None:
print('failed to update')
except Exception as e:
print(e)
I want a function to run every 5 minutes while the main program is still running.
I've found multiple posts on how to make a function run every few seconds but they don't seem to work for me.
This is my program:
from Read import getUser, getMessage
from Socket import openSocket, sendMessage
from Initialize import joinRoom, Console
from question import query_yes_no
from Settings import AIDENT
import string
import sched, time
import urllib.parse
import requests
import subprocess
import sys
import os
s = openSocket()
joinRoom(s)
while True:
try:
try:
readbuffer = s.recv(1024)
readbuffer = readbuffer.decode()
temp = readbuffer.split("\n")
readbuffer = readbuffer.encode()
readbuffer = temp.pop()
except:
temp = ""
for line in temp:
if line == "":
break
if "PING" in line and Console(line):
msgg = (("PONG tmi.twitch.tv\r\n").encode())
print(msgg)
s.send(msgg)
break
user = getUser(line)
message = getMessage(line)
print (user + " > " + message)
PMSG = "/w " + user + " "
if "!ping" in message:
sendMessage(s, "PONG ( i'm working fine )")
except:
pass
I need to run sendMessage() function every 5 minutes without interrupting main program.
You have use threading in case , where your main method will keep on exeuting in separate thread and repeater function will execute after every nth sec
sample code would be like this :
import threading
def printit():
threading.Timer(5.0, printit).start()
print "Hello, World!"
printit()
Give it a try by your self .
You should be using threads. This will create a thread, which simply executes your code and sleeps for 5 min. Instead of running your function, run the last two commands to create the thread and start it.
import threading
import time
def pong():
while True:
sendMessage(s, "PONG ( i'm working fine )")
time.sleep(300)
t = threading.Thread(target=pong, args=(,))
t.start()
I try to display the current windows for each click on the system.
I do this code :
from AppKit import NSWorkspace
def getwindows():
activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
print activeAppName
return
def main():
getwindows()
main()
But only the current windows when i setup the script is displayed.
How can i bind this script in a loop with a click event ?
I already try to use Turtle but some errors appended.
Note that the activeApplication method of NSWorkSpace is deprecated. The following can be used to actively probe the running applications for their active status:
import AppKit
import time
rl = AppKit.NSRunLoop.currentRunLoop()
ws = AppKit.NSWorkspace.sharedWorkspace()
for i in xrange(10):
for app in ws.runningApplications():
if app.isActive():
print "active app:", app.localizedName()
date = AppKit.NSDate.date()
time.sleep(1)
rl.acceptInputForMode_beforeDate_( AppKit.NSDefaultRunLoopMode, date )
Active means it is the receiving keyboard input. Clicking on an application will cause it to become active. Note that the acceptInputForMode method must be called so that property changes are reflected in the current app. Run this program then click on various other applications -- you should see the active app change.
A kind of binding can be done through observers:
import AppKit
ws = AppKit.NSWorkspace.sharedWorkspace()
appL = ws.runningApplications()
class MyClass( AppKit.NSObject ):
def observeValueForKeyPath_ofObject_change_context_(self,
kpath, objid, change, context ):
print "path change", kpath, change['new'], appL[context].localizedName()
obj = MyClass.new()
for i in xrange(len(appL)):
appL[i].addObserver_forKeyPath_options_context_( obj,
"isActive", AppKit.NSKeyValueObservingOptionNew, i )
date = AppKit.NSDate.date().dateByAddingTimeInterval_( 10 )
rl = AppKit.NSRunLoop.currentRunLoop()
rl.acceptInputForMode_beforeDate_( AppKit.NSDefaultRunLoopMode, date )
for app in appL:
app.removeObserver_forKeyPath_( obj, "isActive" )
Run this program same as the last.
There are a few other properties of NSRunningApplication that you could probe/observe (such as hidden) but the list is quite short.
I've written a script that fetches URLs from a file and sends HTTP requests to all the URLs concurrently. I now want to limit the number of HTTP requests per second and the bandwidth per interface (eth0, eth1, etc.) in a session. Is there any way to achieve this on Python?
You could use Semaphore object which is part of the standard Python lib:
python doc
Or if you want to work with threads directly, you could use wait([timeout]).
There is no library bundled with Python which can work on the Ethernet or other network interface. The lowest you can go is socket.
Based on your reply, here's my suggestion. Notice the active_count. Use this only to test that your script runs only two threads. Well in this case they will be three because number one is your script then you have two URL requests.
import time
import requests
import threading
# Limit the number of threads.
pool = threading.BoundedSemaphore(2)
def worker(u):
# Request passed URL.
r = requests.get(u)
print r.status_code
# Release lock for other threads.
pool.release()
# Show the number of active threads.
print threading.active_count()
def req():
# Get URLs from a text file, remove white space.
urls = [url.strip() for url in open('urllist.txt')]
for u in urls:
# Thread pool.
# Blocks other threads (more than the set limit).
pool.acquire(blocking=True)
# Create a new thread.
# Pass each URL (i.e. u parameter) to the worker function.
t = threading.Thread(target=worker, args=(u, ))
# Start the newly create thread.
t.start()
req()
You could use a worker concept like described in the documentation:
https://docs.python.org/3.4/library/queue.html
Add a wait() command inside your workers to get them waiting between the requests (in the example from documentation: inside the "while true" after the task_done).
Example: 5 "Worker"-Threads with a waiting time of 1 sec between the requests will do less then 5 fetches per second.
Note the solution below still send the requests serially but limits the TPS (transactions per second)
TLDR;
There is a class which keeps a count of the number of calls that can still be made in the current second. It is decremented for every call that is made and refilled every second.
import time
from multiprocessing import Process, Value
# Naive TPS regulation
# This class holds a bucket of tokens which are refilled every second based on the expected TPS
class TPSBucket:
def __init__(self, expected_tps):
self.number_of_tokens = Value('i', 0)
self.expected_tps = expected_tps
self.bucket_refresh_process = Process(target=self.refill_bucket_per_second) # process to constantly refill the TPS bucket
def refill_bucket_per_second(self):
while True:
print("refill")
self.refill_bucket()
time.sleep(1)
def refill_bucket(self):
self.number_of_tokens.value = self.expected_tps
print('bucket count after refill', self.number_of_tokens)
def start(self):
self.bucket_refresh_process.start()
def stop(self):
self.bucket_refresh_process.kill()
def get_token(self):
response = False
if self.number_of_tokens.value > 0:
with self.number_of_tokens.get_lock():
if self.number_of_tokens.value > 0:
self.number_of_tokens.value -= 1
response = True
return response
def test():
tps_bucket = TPSBucket(expected_tps=1) ## Let's say I want to send requests 1 per second
tps_bucket.start()
total_number_of_requests = 60 ## Let's say I want to send 60 requests
request_number = 0
t0 = time.time()
while True:
if tps_bucket.get_token():
request_number += 1
print('Request', request_number) ## This is my request
if request_number == total_number_of_requests:
break
print (time.time() - t0, ' time elapsed') ## Some metrics to tell my how long every thing took
tps_bucket.stop()
if __name__ == "__main__":
test()