Your 1st Python Hive Bot Deployment

in #dev3 months ago (edited)

Context

<p dir="auto">This is for beginners.<br /> For when your first Python bot or script for Hive goes to production.<br /> I am not the right guy to post about clean code, but I've learned a few things.<br /> I've made some mistakes and will make more, but maybe I can help you avoid some. <p dir="auto"><img src="https://images.hive.blog/768x0/https://files.peakd.com/file/peakd-hive/felixxx/EorySYrJyMpYZG2zMY4pf5feMJJZ7noKRs8LMyL9LMQ2Fpt4CnuDsvEfMpYoJVSdgHm.png" alt="tipps.png" srcset="https://images.hive.blog/768x0/https://files.peakd.com/file/peakd-hive/felixxx/EorySYrJyMpYZG2zMY4pf5feMJJZ7noKRs8LMyL9LMQ2Fpt4CnuDsvEfMpYoJVSdgHm.png 1x, https://images.hive.blog/1536x0/https://files.peakd.com/file/peakd-hive/felixxx/EorySYrJyMpYZG2zMY4pf5feMJJZ7noKRs8LMyL9LMQ2Fpt4CnuDsvEfMpYoJVSdgHm.png 2x" /> <h2>server ban <p dir="auto">When querying from a public Hive node, that means using https.<br /> The nodes are behind firewalls and other protection.<br /> If you spam queries, you can get banned by these systems.<br /> That's not cool for you and also it's friendlier to just avoid that altogether. <h2>loop <p dir="auto">To infinitely loop a reoccuring job, like a daily compilation of votes or something, <a href="https://en.wikipedia.org/wiki/Cron" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">cron can be good. Or <a href="https://schedule.readthedocs.io/en/stable/index.html" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">schedule. But even then: If you have to make a lot of calls at once, maybe better include time.sleep(2). At least don't blindly iterate over pages of results. <h2>3 second loop <p dir="auto">I'll be writing a lot more about calling for a new block every 3 seconds (block stream).<br /> For now: it's pointless to do the query more than once every 3 seconds.<br /> The main loop should idle for the rest of the time. (time.sleep(3 - (time.time() - start_time))) <h2>async vs. threads <p dir="auto">While true: At the end it's just an infinite loop anyways, but <a href="https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_forever" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">asyncio.loop.run_forever looks nicer.<br /> If it's the first time you see co-routines: Don't worry.<br /> Forget about <a href="https://stackoverflow.com/questions/27435284/multiprocessing-vs-multithreading-vs-asyncio" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">multiprocessing, btw. <h2>signal interrupt <p dir="auto">Using <a href="https://stackoverflow.com/questions/1112343/how-do-i-capture-sigint-in-python" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">an example, I came up with this: <pre><code>import signal, time user_interrupt = False def interrupt_signal_handler(sig, frame): global user_interrupt user_interrupt = True signal.signal(signal.SIGINT, interrupt_signal_handler) def thing(): print("CTRL + C can't...") time.sleep(1) print("...interrupt me") while user_interrupt == False: thing() <p dir="auto">At least you can break out of the loop somehow cleaner.<br /> <strong>Edit: <blockquote> <p dir="auto">It's more important, when working with threads, and then you should combine it with threading.Events, like in <a href="https://www.youtube.com/watch?v=A97QLHAqNuw" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">this video <p dir="auto">You can also use signal for <a href="https://runebook.dev/en/articles/python/library/signal/signal.signal" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">networking and interprocess communication. Powerful. <h2>Linux <p dir="auto">At the end, you'll most likely want to install it all on a server and that's when you'll find that Linux is best for that. At which point you might as well use Linux layer itself to handle task queues and processes, like I already mentioned, when I wrote about cron. And the link, one paragraph above, even demonstrates network sockets. <p dir="auto">That's taking it a bit far though; Most bots can probably live in a single main loop, but keep scalability in mind at least. <p dir="auto">Still ontopic: <a href="https://stackoverflow.com/questions/17544307/how-do-i-run-python-script-using-arguments-in-windows-command-line" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">terminal arguments could be useful. <h2>Server Security <p dir="auto">Talking about remote servers and their security is not something I should be giving advice about.<br /> Still better than nothing: <strong>login via <a href="https://ubuntu.com/server/docs/openssh-server" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">ssh, use <a href="https://en.wikipedia.org/wiki/Fail2ban" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Fail2Ban and <a href="https://ubuntu.com/server/docs/firewalls" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">ufw. <h2>Errors <p dir="auto">Here's a good <a href="https://www.youtube.com/watch?v=8kTlzR4HhWo" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">video on error handling in Python.<br /> In short: don't make errors.<br /> Whether in development or production: if it's a critical error, it should probably crash and you need to fix it. If the error isn't critical, and you can't avoid it, catch and and make it a warning. <h2>Storage <p dir="auto">When your bot crashes, Hive probably keeps running.<br /> When restarting, it can be important to know where it stopped.<br /> Those problems can only be solved by storage and <strong>forget writing your own storage system with file writing and other such experiments.<br /> <a href="https://www.sqlalchemy.org/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">SQLAlchemy (especially sessions) can make stuff robust and scalable. And once you understand it, you already have a strong foundation to learn <a href="https://flask.palletsprojects.com/en/3.0.x/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">flask next... <h2>Service <p dir="auto">It can be fun in the beginning, but servicing bots and managing servers and whatever 24/7 can be a nightmare. So before you commit, think about long term, too.<br /> It can eat up hours and breaks at the worst moments and causes stress.<br /> If it turns into a job, it better be worth it. <h2>Conclusion <p dir="auto">Don't be <strong>that guy.<br /> Shit bots can cause trouble, so please be considerate.<br /> Expecially when broadcasting: Once something was sent, it's out in the world (of blocks) forever. <p dir="auto">That's all I could think of right now. I commented some place else that infinite loops are cringe, so I wanted to share some alternatives and considerations. In the links you should find helpful concepts to get you started on the right foot at least. <p dir="auto"><strong>Please comment, if you want to add something or ask or whatever.
Sort:  

Here's a good video on error handling in Python.

A very well done video: do you use or reccomend using Merry? Also, the concept of bringing errors to the higher scope looks cool and it helped me understanding a bit more the use of "raise". Not that I am now able to implement it in my code, but at least I have a new concept I can try to (slowly) make mine.

SQLAlchemy

This is something I have to start studying, because you mentioned databases so many times and I don't know anything about them... and this is starting to be a problem too big to keep ignoring it.

Btw, in the snippet you shared, what is the signal that interrupts the script changing the boolian value False to True? An input from the coder?

what is the signal that interrupts the script

<p dir="auto">SIGINT (interrupt signal) is a predefined signal-> it's <code>Ctrl + <code>C<br /> The way I use it ensures, that the program finishes thing() before exiting.<br /> What SIGINT stands for was explained in the example I linked a line above my code...<br /> It was confusing me too, when I first saw it: I thought SIGINT was some sort of integer. <blockquote> <p dir="auto">do you use or recommend using Merry? <p dir="auto">No XD <blockquote> <blockquote> <p dir="auto">SQLAlchemy <blockquote> <p dir="auto">This is something I have to start studying <p dir="auto">It's really worth looking into. My SQL is ass. But I understand (for the most part) what SQL does and that's kinda important.<br /> SQLAlchemy isn't necessary to use SQL, but makes it neater Python code.<br /> I'll write a big long series about how I build things and why and I'll be using it, and once you touch flask and flask tutorials (by the same guy I linked the error video from) you can't avoid it. <p dir="auto">I am not using SQL because it is fast (which it is), but mainly because the built in serialization saves me so much work. It's also easy to backup.

snippet you shared

I've thought about and edited the post above.
I now recommend this video:

SIGINT (interrupt signal) is a predefined signal-> it's Ctrl + C

I've seen that it's also in your snippet, but yesterday I somehow only red "can't...", and not "CTRL + C can't..."... nice, I'm blind 😅

I now recommend this video:

I think I might drop a follow to this guy: he has a lot of undervalued content I have to check!

yesterday I somehow only red "can't...", and not "CTRL + C can't..."...

Yesterday it said that. I edited it after replying to you earlier.

I think I might drop a follow to this guy: he has a lot of undervalued content I have to check!

He's got the best flask guide. Not in videos, but on his homepage.
When I first found it, I didn't really get it, because it's more targeted at people, who already tried doing the same things in other languages/libs or by themselves.