Closed pratik-dani closed 4 years ago
Hi there! I've purposely left the repo description blank so far as I'm still testing the UI on my projects.
However, I've seen the other ticket you opened, #3, and here's a working example:
from apschedulerui.web import SchedulerUI
scheduler = BlockingScheduler()
ui = SchedulerUI(scheduler)
ui.start() # Server is now running in a *background* thread.
scheduler.start() # We need to call the BlockingScheduler start method to prevent the script from exiting.
[2020-09-09 11:56:19,232] WARNING in __init__: WebSocket transport not available. Install gevent-websocket for improved performance.
Even after starting the scheduler, I am facing the same issue. I was using Blockingscheduler this time.
Yes, that's a warning from Flask-SocketIO, not from apschedulerui. You can read here about it.
You can pip install gevent-websocket
and that warning will go away.
I did install it but even after installing the localhost:5000 says Not Found (404). I am using Blockingscheduler.
Please try running the following snippet and paste the output here:
import logging
from datetime import datetime
from apscheduler.schedulers.background import BlockingScheduler
from apschedulerui.web import SchedulerUI
logging.basicConfig(level=logging.DEBUG)
scheduler = BlockingScheduler()
ui = SchedulerUI(scheduler)
ui.start() # Server is now running in a *background* thread.
scheduler.add_job(print, 'interval', args=['Job executed'], minutes=60, next_run_time=datetime.now())
scheduler.start() # We need to call the blocking scheduler start method to prevent the script from exiting.
print('This should never be printed!')
INFO:engineio.server:Server initialized for gevent. INFO:apscheduler.scheduler:Adding job tentatively -- it will be properly scheduled when the scheduler starts INFO:socketio.server:emitting event "executor_event" to all [/] INFO:socketio.server:emitting event "job_event" to all [/] INFO:socketio.server:emitting event "jobstore_event" to all [/] INFO:apscheduler.scheduler:Added job "print" to job store "default" INFO:apscheduler.scheduler:Scheduler started INFO:socketio.server:emitting event "scheduler_event" to all [/] DEBUG:apscheduler.scheduler:Looking for jobs to run INFO:apscheduler.executors.default:Running job "print (trigger: interval[1:00:00], next run at: 2020-09-09 18:05:40 IST)" (scheduled at 2020-09-09 18:05:40.634170+05:30) INFO:apscheduler.executors.default:Job "print (trigger: interval[1:00:00], next run at: 2020-09-09 18:05:40 IST)" executed successfully INFO:socketio.server:emitting event "job_event" to all [/] INFO:socketio.server:emitting event "job_event" to all [/] DEBUG:apscheduler.scheduler:Next wakeup is due at 2020-09-09 19:05:40.634170+05:30 (in 3599.934272 seconds) Job executed
The output
But I am not able to access the UI. How to do that?
Can you try running the following snippet and navigating to localhost:5000
in the same machine you're running it?
import logging
import flask
import flask_socketio
logging.basicConfig(level=logging.DEBUG)
web_server = flask.Flask(__name__)
socket_io = flask_socketio.SocketIO(web_server, async_mode='threading')
web_server.add_url_rule('/', 'index', lambda: 'It works!')
socket_io.run(web_server, host='0.0.0.0', port=5000)
Do you see a blank webpage with "It works!" in it?
Do you see a blank webpage with "It works!" in it?
Yes, it shows. But this code will show "It works!" independent of the fact that we have started the scheduler or not. I was in the impression that there will be a UI kind of thing that will have all the list of the jobs which I will be able to manage using the UI as the name was little confusing to me (apschedulerui).
That was just a test to see if you had a problem with the Flask/SocketIO server, it's not serving the Scheduler UI.
I don't understand what you mean with "independent of the fact that we have started the scheduler or not", were you running a scheduler in a different process? There wasn't any scheduler involved in the last snippet I passed to you.
Yeah, there wasn't any scheduler involved and the script worked. I was a little confused my bad, sorry about that. I just want to know how to access the apscheduler UI. Why the Flask/SocketIO server, is not serving the Scheduler UI?
The Scheduler UI will be served on *:5000 using code that's very similar to the last snippet you tested. So I'm not sure why you aren't seeing the UI in your browser in localhost:5000 after running the snippet in my previous comment.
Please try running the following snippet and paste the output here:
import logging from datetime import datetime from apscheduler.schedulers.background import BlockingScheduler from apschedulerui.web import SchedulerUI logging.basicConfig(level=logging.DEBUG) scheduler = BlockingScheduler() ui = SchedulerUI(scheduler) ui.start() # Server is now running in a *background* thread. scheduler.add_job(print, 'interval', args=['Job executed'], minutes=60, next_run_time=datetime.now()) scheduler.start() # We need to call the blocking scheduler start method to prevent the script from exiting. print('This should never be printed!')
Just for reference, this is what you should be seeing in your browser at localhost:5000 after running that snippet:
Which OS are you using?
I am not able to see this UI. Let me try on another machine.
I am using windows 10.
I don't have a Windows machine to test with, but can you run the following snippet to see if navigating to localhost:5000 in your browser also show the "It works" message? Please also provide the output of the script.
import logging
import threading
import time
import requests
import flask
import flask_socketio
logging.basicConfig(level=logging.DEBUG)
class TestWebServer:
def __init__(self):
self._web_server = flask.Flask(__name__)
self._socket_io = None
try:
self._socket_io = flask_socketio.SocketIO(self._web_server, async_mode='gevent')
except ValueError:
self._socket_io = flask_socketio.SocketIO(self._web_server, async_mode='threading')
self._init_endpoints()
self._web_server_thread = None
def start(self, host='0.0.0.0', port=5000, daemon=True):
self._web_server_thread = threading.Thread(target=self._start, name='apscheduler-ui', args=(host, port))
self._web_server_thread.daemon = daemon
self._web_server_thread.start()
def _init_endpoints(self):
self._web_server.add_url_rule('/', 'index', self._index, defaults={'path': ''})
self._web_server.add_url_rule('/<path:path>', 'index', self._index)
def _index(self, path):
return 'It works!'
def _start(self, host, port):
self._socket_io.run(self._web_server, host=host, port=port)
server = TestWebServer()
server.start()
time.sleep(1)
check_request = requests.get('http://localhost:5000')
check_request.raise_for_status()
print(check_request.text)
time.sleep(1e6)
Tested it now on localhost:5000 it shows "It works!"
Can you also provide the output for the script?
That last snippet has the exact same structure I'm using to serve the Scheduler UI, so I'm unsure why the "It works" example is working for you and the Scheduler UI isn't. I may need to try to find a Windows machine to test this during the weekend.
Can you paste the output of pip freeze
here?
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:5000
DEBUG:geventwebsocket.handler:Initializing WebSocket
DEBUG:geventwebsocket.handler:Validating WebSocket request
DEBUG:urllib3.connectionpool:http://localhost:5000 "GET / HTTP/1.1" 200 9
INFO:geventwebsocket.handler:127.0.0.1 - - [2020-09-09 20:58:54] "GET / HTTP/1.1" 200 124 0.003428
It works!
The output of the above code.
I have an Ubuntu wsl on my system if you want I can try running on that machine.
aiohttp==3.6.2
alabaster==0.7.12
altair==4.1.0
anaconda-client==1.7.2
anaconda-navigator==1.9.7
anaconda-project==0.8.3
APScheduler==3.6.3
asn1crypto==1.0.1
aspose-pdf-java-for-jython==1.0.0
astor==0.8.1
astroid==2.3.1
astropy==3.2.1
astunparse==1.6.3
async-timeout==3.0.1
atomicwrites==1.3.0
attrs==19.2.0
autopep8==1.5.2
Babel==2.7.0
backcall==0.1.0
backports.functools-lru-cache==1.5
backports.os==0.1.1
backports.shutil-get-terminal-size==1.0.0
backports.tempfile==1.0
backports.weakref==1.0.post1
beautifulsoup4==4.8.0
bitarray==1.0.1
bkcharts==0.2
bleach==3.1.0
blis==0.4.1
bokeh==1.3.4
boto==2.49.0
boto3==1.14.47
botocore==1.17.47
Bottleneck==1.2.1
cachetools==4.1.0
catalogue==2.0.0
certifi==2019.9.11
cffi==1.12.3
chardet==3.0.4
Click==7.0
cloudpickle==1.2.2
clyent==1.2.2
colorama==0.4.1
comtypes==1.1.7
conda==4.8.3
conda-build==3.18.9
conda-package-handling==1.6.0
conda-verify==3.4.2
contextlib2==0.6.0
convertdate==2.2.1
cryptography==2.7
cycler==0.10.0
cymem==2.0.3
Cython==0.29.13
cytoolz==0.10.0
dask==2.5.2
dateparser==0.7.6
decorator==4.4.0
defusedxml==0.6.0
distributed==2.5.2
dnspython==1.16.0
docutils==0.15.2
email-validator==1.1.1
entrypoints==0.3
ephem==3.7.7.1
et-xmlfile==1.0.1
extract-msg==0.23.3
Faker==4.1.1
fastapi==0.59.0
fastcache==1.1.0
faster-than-requests==0.9.9
fbprophet==0.6
filelock==3.0.12
flake8==3.8.2
Flask==1.1.1
Flask-Limiter==1.4
Flask-Login==0.5.0
Flask-SocketIO==4.3.1
Flask-SQLAlchemy==2.4.4
Flask-WTF==0.14.3
fsspec==0.5.2
future==0.17.1
fuzzywuzzy==0.18.0
gast==0.3.3
getmac==0.8.2
gevent==1.4.0
gevent-websocket==0.10.1
glob2==0.7
google-api-core==1.17.0
google-api-python-client==1.8.3
google-auth==1.15.0
google-auth-httplib2==0.0.3
google-auth-oauthlib==0.4.1
google-pasta==0.2.0
googleapis-common-protos==1.51.0
greenlet==0.4.15
grpcio==1.29.0
gspread==3.6.0
h5py==2.10.0
HeapDict==1.0.1
holidays==0.10.2
html5lib==1.0.1
httplib2==0.18.1
idna==2.8
imageio==2.6.0
imagesize==1.1.0
IMAPClient==2.1.0
implicit==0.4.2
import-java==0.6
importlib-metadata==0.23
ipykernel==5.1.2
ipython==7.8.0
ipython-genutils==0.2.0
ipywidgets==7.5.1
isort==4.3.21
itsdangerous==1.1.0
jdcal==1.4.1
jedi==0.17.0
Jinja2==2.10.3
jmespath==0.10.0
joblib==0.13.2
json5==0.8.5
jsonschema==3.0.2
jupyter==1.0.0
jupyter-client==5.3.3
jupyter-console==6.0.0
jupyter-core==4.5.0
jupyterlab==1.1.4
jupyterlab-server==1.0.6
Keras==2.4.3
Keras-Applications==1.0.8
Keras-Preprocessing==1.1.0
keyring==18.0.0
kiwisolver==1.1.0
korean-lunar-calendar==0.2.1
lazy-object-proxy==1.4.2
libarchive-c==2.8
limits==1.5.1
linkedin-api==1.1.0
llvmlite==0.29.0
locket==0.2.0
lockfile==0.12.2
luigi==3.0.1
LunarCalendar==0.0.9
lxml==4.4.1
Markdown==3.2.2
MarkupSafe==1.1.1
matplotlib==3.2.1
mccabe==0.6.1
menuinst==1.4.16
mistune==0.8.4
mkl-fft==1.0.14
mkl-random==1.1.0
mkl-service==2.3.0
mock==3.0.5
more-itertools==7.2.0
mpmath==1.1.0
msgpack==0.6.1
multidict==4.7.6
multipledispatch==0.6.0
murmurhash==1.0.2
navigator-updater==0.2.1
nbconvert==5.6.0
nbformat==4.4.0
networkx==2.3
nimporter==1.0.2
nltk==3.4.5
nose==1.3.7
notebook==6.0.1
numba==0.45.1
numexpr==2.7.0
numpy==1.18.1
numpydoc==0.9.1
oauth2client==4.1.3
oauthclient==1.0.3
oauthlib==3.1.0
olefile==0.46
opencv-python==4.2.0.34
openpyxl==3.0.0
opt-einsum==3.2.1
packaging==19.2
pandas==0.25.1
pandocfilters==1.4.2
parso==0.7.0
partd==1.0.0
passlib==1.7.2
path.py==12.0.1
pathlib2==2.3.5
patsy==0.5.1
pdf2image==1.13.1
pep8==1.7.1
pickleshare==0.7.5
pikepdf==1.14.0
Pillow==6.2.0
pkginfo==1.5.0.1
plac==1.1.3
plotly==4.7.1
pluggy==0.13.0
ply==3.11
preshed==3.0.2
pretty-html-table==0.9.dev0
probableparsing==0.0.1
prometheus-client==0.7.1
prompt-toolkit==2.0.10
protobuf==3.12.0
psutil==5.6.3
psycopg2==2.8.5
py==1.8.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycodestyle==2.6.0
pycosat==0.6.3
pycparser==2.19
pycrypto==2.6.1
pycurl==7.43.0.3
pydantic==1.6
pydocstyle==5.0.2
pyflakes==2.2.0
pygame==1.9.6
Pygments==2.4.2
pyjnius==1.3.0
pylint==2.4.2
PyMeeus==0.3.7
pymongo==3.10.1
pyodbc==4.0.27
pyOpenSSL==19.0.0
pyparsing==2.4.2
PyPDF2==1.26.0
pyquery==1.4.1
pyreadline==2.1
pyrsistent==0.15.4
PySocks==1.7.1
pyspider==0.3.10
pystan==2.19.0.0
pytest==5.2.1
pytest-arraydiff==0.3
pytest-astropy==0.5.0
pytest-doctestplus==0.4.0
pytest-openfiles==0.4.0
pytest-remotedata==0.3.2
python-crfsuite==0.9.7
python-daemon==2.2.4
python-dateutil==2.8.1
python-engineio==3.13.2
python-http-client==3.2.7
python-jsonrpc-server==0.3.4
python-language-server==0.33.0
python-memcached==1.59
python-slugify==3.0.2
python-socketio==4.6.0
pytz==2019.3
PyWavelets==1.0.3
pywin32==223
pywinpty==0.5.5
PyYAML==5.3
pyzmq==18.1.0
QtAwesome==0.6.0
qtconsole==4.5.5
QtPy==1.9.0
redis==3.5.3
regex==2020.7.14
requests==2.22.0
requests-oauthlib==1.3.0
retry==0.9.2
retrying==1.3.3
rope==0.14.0
rq==1.4.3
rsa==4.0
ruamel-yaml==0.15.46
s3transfer==0.3.3
scikit-image==0.15.0
scikit-learn==0.21.3
scipy==1.4.1
seaborn==0.9.0
selenium==3.141.0
Send2Trash==1.5.0
sendgrid==6.4.1
sentry-sdk==0.14.4
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.12.0
slacker==0.14.0
snowballstemmer==2.0.0
sortedcollections==1.1.2
sortedcontainers==2.1.0
soupsieve==1.9.3
spacy==2.2.4
Sphinx==2.2.0
sphinxcontrib-applehelp==1.0.1
sphinxcontrib-devhelp==1.0.1
sphinxcontrib-htmlhelp==1.0.2
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.2
sphinxcontrib-serializinghtml==1.1.3
sphinxcontrib-websupport==1.1.2
spyder==3.3.6
spyder-kernels==0.5.2
SQLAlchemy==1.3.9
srsly==1.0.2
starkbank-ecdsa==1.0.0
starlette==0.13.4
statsmodels==0.10.1
sympy==1.4
tables==3.5.2
tabula-py==2.1.0
tblib==1.4.0
tensorboard==2.2.2
tensorboard-plugin-wit==1.6.0.post3
tensorflow==2.2.0
tensorflow-estimator==2.2.0
termcolor==1.1.0
terminado==0.8.2
testpath==0.4.2
text-unidecode==1.3
thinc==7.4.0
tika==1.24
toolz==0.10.0
tornado==5.1.1
tqdm==4.36.1
traitlets==4.3.3
typed-ast==1.4.1
tzlocal==1.5.1
unicodecsv==0.14.1
unique-id==1.0.1
uritemplate==3.0.1
urllib3==1.24.2
usaddress==0.5.10
wasabi==0.6.0
wcwidth==0.1.7
webencodings==0.5.1
Werkzeug==0.16.0
widgetsnbextension==3.5.1
win-inet-pton==1.1.0
win-unicode-console==0.5
wincertstore==0.2
wrapt==1.11.2
WTForms==2.3.1
xgboost==0.90
xlrd==1.2.0
XlsxWriter==1.2.1
xlwings==0.15.10
xlwt==1.3.0
yapf==0.30.0
yarl==1.4.2
zict==1.0.0
zipp==0.6.0```
I don't see apschedulerui as one of the packages you have installed, from the output of pip freeze
. Did you check out this repo and you're using the "apschedulerui" folder as the package?
If that's the case, you need to install the package from pip, with pip install apschedulerui
and you can safely remove any folder you checked out from GitHub.
That would explain why you're seeing a 404 error when navigating to localhost:5000, the Scheduler UI is trying to serve the index.html file with a path relative to the package structure that will never be found if the package is not properly installed.
Ok. Now I understand the issue. Now it's working. Thanks a lot. The UI looks amazing.
You're welcome! Glad that we figured it out.
Just bear in mind it's still in an early stage of development and a few issues may still arise!
I would be happy to help if you need any. I am going to implement this in my tool. I saw the image of this UI on dribbble. The UI is perfect.
Thanks for the help!
One last question the UI on dribbble has Executers, Jobstores and Stop scheduler buttons in them. Are they part of this version? If yes, then I am not able to utilize them.
Executors and Jobstores tab isn't yet implemented, but it'll be a simple list of the executors and job stores the scheduler has, which almost every time is only 1 of each and doesn't mean much.
Stopping the scheduler may never be implemented, because when I tested it the re-start method didn't work (i.e. the scheduler would say "Running", yet jobs wouldn't execute again). So unless I find a way of making the re-start work, I won't be implementing it. Pausing and resuming the scheduler has a similar effect, though, and you can stop it from running jobs by pausing it.
Can you add a little documentation on how to run this repo.