func must be a callable or a textual reference to one - python

I am trying to run a function every 2 minutes, and I use apscheduler for this. However, when I run this I get the following error:
Traceback (most recent call last):
File "main_forecast.py", line 7, in <module>
scheduler.add_job(get_warnings(), 'interval', seconds = 120)
File "/home/anastasispap/.local/lib/python3.6/site-packages/apscheduler/schedulers/base.py", line 434, in add_job
job = Job(self, **job_kwargs)
File "/home/anastasispap/.local/lib/python3.6/site-packages/apscheduler/job.py", line 49, in __init__
self._modify(id=id or uuid4().hex, **kwargs)
File "/home/anastasispap/.local/lib/python3.6/site-packages/apscheduler/job.py", line 170, in _modify
raise TypeError('func must be a callable or a textual reference to one')
TypeError: func must be a callable or a textual reference to one
And here's the code:
from apscheduler.schedulers.background import BackgroundScheduler
from enemies_info import get_warnings
import time
scheduler = BackgroundScheduler()
scheduler.add_job(get_warnings(), 'interval', seconds = 120)
scheduler.start()
while True:
time.sleep(120)
The function I want to run every 2 minutes is get_warnings.
def get_warnings():
print('get_warning has been run')
names = []
types = []
number_of_threats = 0
forecast_weather()
for i in range(0, number_of_enemies):
enemies = info["enemies"][i]
name = enemies["name"]
type = enemies["type"]
temperature = enemies["temperature"]
temperature = temperature.split("-")
min_temp = temperature[0]
max_temp = temperature[1]
for i in range(len(temperatures)):
if avg_temps[i] <= str(max_temp):
names.append(name)
types.append(type)
number_of_threats += 1
break
os.chdir('..')
write_data(number_of_threats, names, types)
move_to_github()

You are calling the function get_warnings, instead of providing it as a callable. Try:
scheduler.add_job(get_warnings, 'interval', seconds = 120)

Related

Calling a class method from a different file using Schedule Module in Python

I'm trying to call a method from a class that is in a different file. This is how my code looks:
main.py
###Imports
import funct as f
import schedule
import time
###More Imports
###Grabbing GPS data from user and assigning values
bboxsize = f.find(userLat, userLng, userRad)
if __name__ == '__main__':
r = f.find.radar(bboxsize) ### <---- Line 14
schedule.every(5).seconds.do(r)
while True:
schedule.run_pending()
time.sleep(1)
funct.py
###Imports
class find:
def __init__(self, userLat, userLng, userRad):
self.userLat = userLat
self.userLng = userLng
self.userRad = userRad
def bboxFormula(self):
### Lots of code that is not important to this
return bboxsize
def radar(self, bboxsize):
api = OpenSkyApi(username='###', password='###')
states = api.get_states(bbox=bboxsize)
print(f"vvvvvv| {time.ctime(time.time())} |vvvvvv")
print("------------------------------------------")
for s in states.states:
print("Callsign: %r, Latitude: %r, Longitude: %r, Altitude (meters): %r, Velocity %r)" % (s.callsign, s.latitude, s.longitude, s.geo_altitude, s.velocity))
print("------------------------------------------")
When running this I get:
Traceback (most recent call last):
File "/##/##/##/##/main.py", line 14, in <module>
r = f.find.radar(bboxsize)
TypeError: find.radar() missing 1 required positional argument: 'bboxsize'
I can run all of this in one file without classes, so I know it works. I have been messing with this for a while getting all sorts of errors with every change I make.
Is there something that I'm missing or is there no way for me to do this with the Schedule Module?
I’m just guessing here, but I think you had different code when it was all one file.
Now with two files I think you meant to write this:
find = f.find(userLat, userLng, userRad)
boxsize = find.bboxFormula()
if __name__ == '__main__':
r = lambda :find.radar(bboxsize) ### <---- Line 14
schedule.every(5).seconds.do(r)
while True:
schedule.run_pending()
time.sleep(1)

Multiprocessing using partial() throws ForkingPickler error

I am trying to crawl abstracts from PubMed and filtering them using regex via python. To speed things up, I wanted to use pythons multiprocessing pool.
My code looks like the following:
import multiprocessing as mp
from functools import partial
from typing import List, Tuple
def beautify_abstract(abstract: str, regex: str):
import re
result: str = ""
last_start = 0
matches = re.finditer(regex, abstract, re.MULTILINE)
for matchNum, match in enumerate(matches, start=1):
result += abstract[last_start:match.start()]
result += "<b>"
result += abstract[match.start():match.end()]
result += "</b>"
last_start = match.end()
result += abstract[last_start:]
return result
def get_doi(pim: str, regex: str):
from Bio import Entrez
from Bio.Entrez import efetch
import re
from metapub.convert import pmid2doi
Entrez.email = "Your.Name.Here#example.org"
print(f"Processing {pim}")
abstract_handle = efetch(db="pubmed", id=pim, retmode='text', rettype='all')
abstract = abstract_handle.read()
abstract_handle.close()
if re.search(regex, abstract, re.MULTILINE) is not None:
docsum_handle = efetch(db="pubmed", id=pim, retmode='text', rettype='docsum').read()
docsum = docsum_handle.read()
try:
doi = pmid2doi(pim)
except:
doi = "UNKNOWN"
return f"{doi}"
return ""
def get_pim_with_regex_list(keywords: List[str]) -> List[str]:
from Bio import Entrez
Entrez.email = "Your.Name.Here#example.org"
searchterm = " ".join(keywords)
pims = []
handle = Entrez.esearch(db="pubmed", retstart=0, retmax=0, term=searchterm, idtype="acc")
record = Entrez.read(handle)
handle.close()
count = int(record['Count'])
if count > 100000:
retmax = 100000
else:
retmax = count
retstart = 0
while retstart < count:
handle = Entrez.esearch(db="pubmed", retstart=retstart, retmax=retmax, term=searchterm, idtype="acc")
record = Entrez.read(handle)
handle.close()
for pim in record['IdList']:
pims.append(pim)
retstart += retmax
return pims
if __name__ == '__main__':
keywords = ["keyword1", "keyword2"]
pim_list = get_pim_with_regex_list(keywords)
regex = "keyword1 keyword2"
worker_fn = partial(get_doi, regex=regex)
pool = mp.Pool(mp.cpu_count())
entries = pool.map(worker_fn, pim_list)
pool.close()
pool.join()
When I run the given code, I get the following error:
Traceback (most recent call last):
File "/usr/lib/python3.9/multiprocessing/process.py", line 315, in _bootstrap
self.run()
File "/usr/lib/python3.9/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3.9/multiprocessing/pool.py", line 114, in worker
task = get()
File "/usr/lib/python3.9/multiprocessing/queues.py", line 368, in get
return _ForkingPickler.loads(res)
TypeError: __new__() missing 2 required positional arguments: 'tag' and 'attributes'
Process ForkPoolWorker-4:
Traceback (most recent call last):
File "/usr/lib/python3.9/multiprocessing/process.py", line 315, in _bootstrap
self.run()
File "/usr/lib/python3.9/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3.9/multiprocessing/pool.py", line 114, in worker
task = get()
File "/usr/lib/python3.9/multiprocessing/queues.py", line 368, in get
return _ForkingPickler.loads(res)
TypeError: __new__() missing 2 required positional arguments: 'tag' and 'attributes'
I did some digging into multiprocessing with python and found out that only python native types are supported as parameters (enforced by the ForkingPickler).
Assuming that str is a native type, the code should work... Currently, I am completely lost and have no idea what may be the problem.
As suggested, I uploaded a minimal (sequential) working example here
Is there any way to fix this problem or at least diagnose the real issue here?

How to correctly use enterabs from scheduler

I'm trying to schedule something to run periodically, using the code below:
import sched
import time
from datetime import datetime, timedelta
def foo(s, t_end):
now = datetime.now()
print(now)
# Schedule the next run of this function, but only if it'll be before 't_end'
next_run = now + timedelta(seconds=1)
if next_run <= t_end:
s.enter(1, 1, foo, (s, t_end,))
# s.enterabs(next_run, 1, foo, (s, t_end,)) # <-- why doesn't this work?
if __name__ == '__main__':
s = sched.scheduler(time.time, time.sleep)
t_end = datetime.now() + timedelta(seconds=5)
foo(s, t_end)
s.run()
This runs exactly like it should... the script calls foo exactly 5 times and then exits (with 1 second delay between the calls).
But if I change the s.enter(...) to s.enterabs(...) and pass in the calculated time when foo should be called again, it throws the following error:
Traceback (most recent call last):
File "/tmp/test.py", line 18, in <module>
s.run()
File "/usr/lib/python3.9/sched.py", line 141, in run
if time > now:
TypeError: '>' not supported between instances of 'datetime.datetime' and 'float'
What am I doing wrong?
OK I figured this out. In the call to s.enterabs(...), I need to pass next_run.timestamp() as the first argument (not just next_run).

'_csv.reader' object is not callable

This program is supposed to emit sound based on a CSV file.
There is a frequency range in the dataset of 37-32677. In the beginning I didn't add this in and got this same error message. I tried adding in this range and I am still getting the same error.
import winsound
import csv
winsound.Beep(261,100)
def preload(filename):
file = open(filename)
data = csv.reader(file)
return data
def getNote(sensorVal):
return int(sensorVal * 75)
def setup():
cleanedData = {}
notes = []
data = preload("data1.csv")
for row in data(range(36,32677)):
print(row)
if row[1] != "trial number":
sensorVal = float(row[4])
channel = int(row[7])
if channel not in cleanedData:
cleanedData[channel] = []
cleanedData[channel].append({"sensorVal":sensorVal})
notes.append(getNote(sensorVal))
return cleanedData,notes
def play(notes,time):
for note in notes:
winsound.Beep(note,time)
data, notes = setup()
play(notes, 200)
Error message:
Traceback (most recent call last):
File "C:/Users/clair/PycharmProjects/winSound/main.py", line 32, in <module>
data, notes = setup()
File "C:/Users/clair/PycharmProjects/winSound/main.py", line 16, in setup
for row in data(range(36,32677)):
TypeError: '_csv.reader' object is not callable
Process finished with exit code 1

TypeError: 'NoneType' object is not callable, but not sure why. Can someone please explain?

Trying to create a python script to do a periodic check on a service. If it is not running, it will auto-start it. Here is the code:
import win32serviceutil
from sched import scheduler
from time import time, sleep
s = scheduler(time, sleep)
def run_periodically(start, end, interval, func):
event_time = start
while event_time < end:
s.enterabs(event_time, 0, func, ())
event_time += interval
s.run()
if __name__ == '__main__':
machine = 'George'
service = 'Hamachi2Svc'
action = 'start'
def service_info(action, machine, service):
if win32serviceutil.QueryServiceStatus(service, machine)[1] == 4:
print "%s is currently running" % service
else:
print "%s is *not* running" % service
print "%s is starting..." % service
win32serviceutil.StartService(service, machine)
print '%s started successfully' % service
run_periodically(time()+5, time()+10, 1, service_info(action, machine, service))
Here is the error produced:
Traceback (most recent call last):
File "C:\Python27\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py", line 323, in RunScript
debugger.run(codeObject, __main__.__dict__, start_stepping=0)
File "C:\Python27\Lib\site-packages\pythonwin\pywin\debugger\__init__.py", line 60, in run
_GetCurrentDebugger().run(cmd, globals,locals, start_stepping)
File "C:\Python27\Lib\site-packages\pythonwin\pywin\debugger\debugger.py", line 655, in run
exec cmd in globals, locals
File "C:\Users\Administrator\Desktop\HamachiDestroyerV.01.py", line 1, in <module>
import win32serviceutil
File "C:\Users\Administrator\Desktop\HamachiDestroyerV.01.py", line 13, in run_periodically
s.run()
File "C:\Python27\lib\sched.py", line 117, in run
action(*argument)
TypeError: 'NoneType' object is not callable
I was wondering if anyone could lend their expertise and inform me what I'm doing wrong. I'm still a beginner in python, but this isn't the first program I have made.
You register the return value of service_info(); that function returns None.
If you wanted service_info() to be called by the scheduler instead, you'll need to register the reference to the function itself, together with a tuple of arguments:
run_periodically(time()+5, time()+10, 1, service_info, (action, machine, service))
and adjust run_periodically() to accept the arguments and pass that on to the scheduler.enterabs() method:
def run_periodically(start, end, interval, func, args=()):
event_time = start
while event_time < end:
s.enterabs(event_time, 0, func, args)
event_time += interval
s.run()

Categories

Resources