[ENG/ITA] Python and Hive: Learning from Other Hiveans!

cover


La versione italiana si trova sotto quella inglese

The italian version is under the english one


Python and Hive: Learning from Other Hiveans!

In my - short - journey to learn Python I read a few tutorials, watched a few videos and followed a short free online course provided by Harvard University.

After that, after about a month, I had to stop due to various work commitments that forced me to put everything on hold, which also led me to forget some of what I had just learnt.

Then in August I was finally able to get back on track and, thanks to the summer holidays, I was able to dedicate a month or so to writing some scripts, starting a small project/exercise on Hive: creating something that could have a real application gave me the motivation to keep practising and, even though the holidays are now unfortunately over, I'm still making an effort every night to find some time to make more progress.

Learning something alone isn't easy though, and I've often found myself thinking that it would have been nice to know someone I could ask a few questions from time to time...

That's also why I started this sort of series on ‘Hive and Python’: sharing my first steps is a way both to ‘expose’ myself, and thus make me feel even more motivated to try and make progress, and to tell the rest of the world - well, Hive! - that I'm venturing into a world I know little about and about which I'd love to get advice from more experienced people.

And so it was great when @slobberchops - an Orca ( of Hive) - noticed me after reading one of my comments to one of his posts, offered valuable advice and shared some of his snippets, i.e. small bits of code, with me.

Thanks to these and to a recent post of his, I began to understand what an API is and how interfacing with it enables one to obtain information from Hive, without the need to use specific libraries which, however useful, are at risk of not being updated and becoming obsolete.

But between starting to understand something and putting it into practice there is a huge gap, and this is where @felixxx came to my rescue: reading his last post a whole world opened up to me, and I found myself holding a script that @felixxx himself made available to everyone.

With this script you can easily retrieve information from the Hive blockchain, so that you can later use it at your will.

This script can then be integrated with other methods supported by Hive's native API, making it a powerful and extremely flexible tool.

Thanks to the invaluable and incredible help I received from these two Hiveans, I can now update my two scripts, making them much more solid, readable and correct.

Once this is done, I can then also work on the third one, which I had started working on but which, at this point, I might want to redo from scratch.

The point, however, is that Hive is not just a place to publish content in the hope of receiving rewards, but it is - above all - a place to exchange ideas, compare ideas, learn from others, help each other and meet new people.

The more time passes, the happier I am to have started this journey on Hive, which is evolving into something increasingly beautiful and interesting!

Now, before closing this post, I would like to share with you below the incredible script made available by @felixxx, with some comments added by me to show - I hope - that I was able to understand how it works... at least this way @felixxx will know that I not only tested his code but also made an effort to understand it 😂


Here is the code written by @felixxx


import requests

# interact with the API 
def get_response(data, url, session: requests.Session):
    request = requests.Request("POST", url=url, data=data).prepare() # prepare request    
    response = session.send(request, allow_redirects=False) # send request, keep session, get response
    return response

# config the API call and then return the response
def get_properties(url, session: requests.Session):
    data = '{"jsonrpc":"2.0", "method":"database_api.get_dynamic_global_properties", "id":1}'
    response = get_response(data, url, session)
    properties = response.json()['result'] # deserialize response, access 'result' value (type: dict)
    return properties

# same as above, but with a different API call in the same session
def get_block(num, url, session: requests.Session):
    data = f'{"jsonrpc":"2.0", "method":"block_api.get_block", "params":{{"block_num":{num}}},"id":1}'
    response = get_response(data, url, session)
    block = response.json()['result']['block'] # deserialize response, access 'result' value (type: dict), then access 'block' value (type: dict)
    return block

# open the session, trigger the requests, and return the response
def get_last_block(url):
    with requests.Session() as session: # mantain certain parameters across requests
        last_irreversible_block_num = get_properties(url, session)['last_irreversible_block_num'] # access dict and get value (type: int)
        last_block = get_block(last_irreversible_block_num, url, session)
        return last_block



The code is owned by @felixxx and I do not take ownership or authorship of it in any way.

Only the useless comments are mine 😅.


cover made with Bing AI and edited with GIMP

to support the #OliodiBalena community, @balaenoptera is 3% beneficiary of this post


If you've read this far, thank you! If you want to leave an upvote, a reblog, a follow, a comment... well, any sign of life is really much appreciated!


Versione italiana

Italian version


cover

Python and Hive: Imparare dagli Altri Hivers!

Nel mio - breve - percorso di apprendimento di Python ho letto un po' di tutorial, visto qualche video e seguito un breve corso gratuito online messo a disposizione dall'Università di Harvard.

Dopo di che, passato circa un mese, mi sono dovuto fermare a causa di vari impegni lavorativi che mi hanno costretto a mettere in pausa tutto quanto, portandomi anche a dimenticare un po' di quanto appena imparato.

Poi ad Agosto ho finalmente avuto modo di riprendere in mano la situazione e, grazie alle ferie estive, ho potuto dedicarmi per un mesetto a scrivere qualche script, avviando un piccolo progetto/esercizio su Hive: creare qualcosa che potesse avere un'applicazione reale mi ha motivato a continuare ad esercitarmi e, anche se adesso le ferie sono purtroppo finite, mi sto sforzando la sera di trovare ogni volta che riesco un po' di tempo per cercare di fare altri progressi.

Imparare qualcosa alla cieca non è facile però e spesso mi sono ritrovato a pensare che sarebbe stato bello conoscere qualcuno a cui poter fare ogni tanto qualche domanda...

Anche per questo ho avviato questa sorta di serie su "Hive e Python": condividere i miei primi passi è un modo sia per "espormi", e quindi sentirmi ancora più motivato a cercare di fare progressi, sia per dire al resto del mondo - be', Hive! - che mi sto avventurando in un mondo del quale so poco e sul quale mi piacerebbe ricevere consigli da persone più esperte.

Ed è stato perciò bellissimo quando @slobberchops - un'Orca (di Hive) - mi ha notato, dopo aver letto un mio commento ad un suo post, mi ha dato preziosi consigli ed ha condiviso con me alcuni suoi snippets, ossia piccole parti di codice.

Grazie a questi e ad un suo recente post ho cominciato a capire cosa sia un'API e come interfacciarsi con essa consenta di ottenere informazioni da Hive, senza bisogno di utilizzare librerie apposite che, per quanto utili, rischiano di non venire aggiornate e di diventare obsolete.

Ma fra il cominciare a capire qualcosa ed il metterlo in pratica c'è un abisso ed è qui che è giunto in mio soccorso @felixxx: leggendo il suo ultimo post mi si è aperto un mondo e mi sono ritrovato tra le mani uno script messo a disposizione per tutti da @felixxx stesso.

Con questo script è possibile ottenere facilmente informazioni dalla blockchain di Hive, così da poterle poi utilizzare a proprio piacimento.

Questo script può poi essere integrato con altri metodi supportati dalle API native di Hive, rendendolo così uno strumento potentissimo ed estremamente flessibile.

Grazie al prezioso ed incredibile aiuto che ho ricevuto da questi due Hivers potrò adesso aggiornare i miei due scripts, rendendoli molto più solidi, leggibili e corretti.

Fatto questo potrò poi preparare anche il terzo, sul quale avevo cominciato a lavorare ma che, a questo punto, forse mi conviene rifare da capo.

Il punto, però, è che Hive non è solo un luogo dove pubblicare contenuti nella speranza di ricevere delle ricompense, ma è - soprattutto - un posto dove scambiarsi idee, confrontarsi, imparare dagli altri, aiutarsi a vicenda e conoscere nuove persone.

Più passa il tempo e più sono contento di aver iniziato questo viaggio su Hive, che si sta evolvendo in qualcosa di sempre più bello ed interessante!

Ora, prima di chiudere il post, vi riporto qua sotto l'incredibile script messo a disposizione da @felixxx, con accanto dei commenti aggiunti da me per dimostrare - spero - che sono riuscito a capirne il funzionamento... almeno così @felixxx saprà che il suo codice non solo l'ho testato ma mi sono anche sforzato di capirlo 😂


Ecco il codice creato da @felixxx


import requests

# interact with the API: send request, get response
def get_response(data, url, session: requests.Session):
    request = requests.Request("POST", url=url, data=data).prepare() # prepare request    
    response = session.send(request, allow_redirects=False) # send request, keep session, get response
    return response

# config the API call (i.e., the request) and, when getting the response, access it to find the value we are looking for
def get_properties(url, session: requests.Session):
    data = '{"jsonrpc":"2.0", "method":"database_api.get_dynamic_global_properties", "id":1}' # the request
    response = get_response(data, url, session)
    properties = response.json()['result'] # deserialize response, access 'result' value (type: dict)
    return properties

# same as above, but with a different API call in the same session
def get_block(num, url, session: requests.Session):
    data = f'{"jsonrpc":"2.0", "method":"block_api.get_block", "params":{{"block_num":{num}}},"id":1}' # a different request
    response = get_response(data, url, session)
    block = response.json()['result']['block'] # deserialize response, access 'result' value (type: dict), then access 'block' value (type: dict)
    return block

# open the session, trigger the requests, collect the needed values inside the responses and return them
def get_last_block(url):
    with requests.Session() as session: # mantain certain parameters across requests
        last_irreversible_block_num = get_properties(url, session)['last_irreversible_block_num'] # access dict and get value (type: int)
        last_block = get_block(last_irreversible_block_num, url, session) # use that value as one of the arguments of the 2nd request in the same session
        return last_block



Il codice è di @felixxx e non me ne assumo in alcun modo la titolarità o paternità.

Di mio ci sono solo gli inutili commenti 😅


cover realizzata con Bing AI ed editata con GIMP

a supporto della community #OliodiBalena, il 3% delle ricompense di questo post va a @balaenoptera

Se sei arrivato a leggere fin qui, grazie! Se hai voglia di lasciare un upvote, un reblog, un follow, un commento... be', un qualsiasi segnale di vita, in realtà, è molto apprezzato!

Posted Using InLeo Alpha



0
0
0.000
21 comments
avatar

!discovery 30
@tipu curate 2

0
0
0.000
avatar

creating something that could have a real application gave me the motivation to keep practising

💯

That's how I taught myself.

Only the useless comments are mine 😅.

omg, you've ruined it! 😅

Having you work with my examples was quite rewarding.
You naturally understood what the functions could be used for; That's why I chose them.
So instead of me explaining, you had a chance to experience it happening and come to your own conclusions. Which was the plan.

I'll continue to post stripped down, clean and robust code.
I'll provide more detail in the comment section, but try to keep the main posts clean.

0
0
0.000
avatar

That's how I taught myself.

Really!? You are so good and you have done all by yourself? Dang, that's beyond motivating 😅

omg, you've ruined it! 😅

I know 🤣 but don't worry, the comments are there only for the sake of this post: I promise I won't put any when I'll use your code in my scripts ahahah

So instead of me explaining, you had a chance to experience it happening and come to your own conclusions. Which was the plan.

I love your approach, tbh: it challenges the reader to actively learn and this is by far more efficient than just reading an explanation. By trying myself your code I was able to ask myself why you did something, look for an answer by using my brain and than, finally, understand what was doing what and, most importantly, why.

Sessions/Requests are still a bit obscure for me, though, but I can't hope to understand everything immediately, so I'll keep checking the docs and experimenting with different API call to strengthen my knowledge.

0
0
0.000
avatar

Really!? You are so good and you have done all by yourself? Dang, that's beyond motivating 😅

Yes.
I am not even good.
The stuff I build is far from industry standard.

What seems impressive now, will look like a joke another month in.
Once you've built a few things, you'll notice.
Repetition -> learning.

Sometimes I do totally unrelated stuff and suddenly I understand something that I tried weeks ago...

Sessions/Requests are still a bit obscure for me, though, but I can't hope to understand everything immediately, so I'll keep checking the docs and experimenting with different API call to strengthen my knowledge.

Yeah... I can tell by your comments on the code, that it hasn't 'clicked' for you.
Thing is: that has nothing to do with HIVE, but you just need more practice with Python and code in general.
...and there are enough Python tutorials out there.
If something isn't clear, I am happy to help, but I can't also try to teach Python in my tutorials.

That with statement is very pythonic and it's powerful.
Other languages don't even have that concept...

For now: Please trust me, it's the cleanest way to go about it.
I use it for reasons and they will become clearer when I continue.
It's worth exploring...

I love your approach, tbh: it challenges the reader to actively learn and this is by far more efficient than just reading an explanation.

That's it. Feels good that it worked for you.
But it really only works, when people actually try to use it.
Tagging @slobberchops for good measure here.

0
0
0.000
avatar

I can tell by your comments on the code, that it hasn't 'clicked' for you.

Still far from clicking, but slowly I'll get it :)

Please trust me

100% trust! I know that "with" is very powerful and I was using it to open a file, but from your code I learned that it can do much more, so yup, just from a few lines of yours thare's a lot of stuff which are very much worth exploring!

If something isn't clear, I am happy to help, but I can't also try to teach Python in my tutorials.

Your comments and posts are already way much more than what I was hoping to find :)

0
0
0.000
avatar
(Edited)

I know that "with" is very powerful and I was using it to open a file

...and close it.

with keeps any session (writing files, accessing databases, http sessions) open and closes it, too. This leads to cleaner structure and cleaner code.
(The other way would be using open() and close() functions, which can lead to all sorts of trouble)

btw did you manage to use condenser's get_accounts function?

0
0
0.000
avatar
(Edited)

I was aware that it open and close a file, but I didn't know it could be used for different tasks, like databases and http sessions: a knowledge worth remembering... and mastering :)

btw did you manage to use condenser's get_accounts function?

Today I tried a bit the condenser_api.get_discussions_by_author_before_date, because I needed to see what info were submitted when publishing a post... and after that I started experimenting a bit 😅

def get_discussions_before_date(url, num, session: requests.Session):
    data = f'{{"jsonrpc":"2.0", "method":"condenser_api.get_discussions_by_author_before_date", "params":["arc7icwolf","","2024-09-12T22:49:43",{num}], "id":1}}'
    response = get_response(data, url, session)
    discussions = response.json()['result']
    reputation_list = []
    for discussion in discussions:
        reputation = discussion['author_reputation']
        if reputation not in reputation_list:
            reputation_list.append(reputation)
    return reputation_list

And here is when I found that my reputation hasn't changed with the last 100 posts I published 😂

EDIT: unless I made a mistake, because now I'm trying to change the date and it keeps giving me the same results as before:

import requests

def get_response(data, url, session: requests.Session):
    request = requests.Request("POST", url=url, data=data).prepare()
    response = session.send(request, allow_redirects=False)
    return response

def get_discussions_before_date(url, num):
    with requests.Session() as session:
        data = f'{{"jsonrpc":"2.0", "method":"condenser_api.get_discussions_by_author_before_date", "params":["arc7icwolf","","2024-07-29T12:23:09",{num}], "id":1}}'
        response = get_response(data, url, session)
        discussions = response.json()['result']
        reputation_list = []
        for discussion in discussions:
            print(discussion)
            reputation = discussion['title']
            if reputation not in reputation_list:
                reputation_list.append(reputation)
        return reputation_list


def main():
    url = "https://api.deathwing.me"
    num = 3
    rep_list = get_discussions_before_date(url, num)
    print(rep_list)


if __name__ == "__main__":

    main()

No matter what date I set, I always see the data and title about my last 3 posts... I guess I'll try to understand what I messed up tomorrow after a good sleep 😴

0
0
0.000
avatar

Condenser provides 'higher level' information. The further you deviate from the core functions of Hive, the more complicated (and unreliable) it gets.
Reputation for example is abstracted. It never was a core feature of Hive, but was built on top of it.

And here is when I found that my reputation hasn't changed with the last 100 posts I published 😂

Whenever you get a vote (up or down) it affects your reputation.
So yeah, something went wrong.

I am not familiar with all calls in the documentation.
I have never touched get_discussions_by_author_before_date
There's also no guarantee that the calls are properly documented and I raged about that a while ago:
https://peakd.com/dev/@felixxx/hive-api-reference-incomplete
I have since been told that the documentation is incomplete on purpose, because the higher level (hivemind) stuff, will be abandoned in the future in favor of a HAF infrastructure.

I am pretty sure there is no extra table that saves how high your reputation was at a given time. That would be a very long database table that makes an entry after every vote you ever received and that for every user... too much data for too little benefit...

I could look into the above call more closely, depending on how important it is for you.

Generally, I'd say: stay away from get_discussion and anything reputation for now. They are soft.
block_api, account_api are core features and the most reliable...

0
0
0.000
avatar

I have since been told that the documentation is incomplete on purpose

What an unusual purpose LOL also considering that I guess that this situation is going on since a long time, and this doesn't sound like something which could help increase adoption...

I could look into the above call more closely, depending on how important it is for you.

Don't worry, I chose that key only to see if was able to access it, but I could have chosen a different one! oc I had to choose one that wasn't working properly among all the available keys 🤣

Generally, I'd say: stay away from get_discussion and anything reputation for now. They are soft.

Gotcha!

0
0
0.000
avatar

Well...

I actually went ahead an wrote a whole post about it...

0
0
0.000
avatar

Already seen and upvoted! :) Happy to see you posting more snippets and useful tips! As soon as I can I will read again it and use it to make more progress with my coding.

0
0
0.000
avatar

Se solo poteste dedicarvi a queste piattaforme senza bisogno di lavorare offline sarebbe il massimo (ecco perchè se fosse un posto in cui ci fareste uno stipendio, poi non dovreste fare i salti mortali e magari pure nottate da pipistrelli (come le mie🤣) per terminare questi progetti:
untitled.gif
Certo, se foste filippini ce la fareste davvero, grazie al valore sproporzionato del dollaro rispetto al peso filippino e alla spensieratezza del loro governo che se ne infischia di tutto quello che i cittadini fanno al di fuori del territorio e infatti non devono nemmeno portare in dichiarazione dei redditi alcun freela manco se guadagnassero milioni, beati loro.
!LOLZ

0
0
0.000
avatar

Magari, sarebbe così bello potersi dedicare solo a questo! Anche se onestamente sono talmente un principiante che attualmente nessuno mi pagherebbe per fare nulla 😅

Certo se un giorno riuscissi a tirarci fuori qualcosa, la prenderei seriamente in considerazione l'idea di trasferirmi da qualche parte dove il costo della vita è più bassa: d'altra parte meglio una vita semplice ma tranquilla che una in cui bisogna vivere perennemente con l'ansia e l'agitazione... per cosa poi? Alla fine uno non è che si possa godere molto quando non ha tempo di fare nulla che non sia lavorare...

!PIZZA

0
0
0.000
avatar
(Edited)

No, non dico solo per i codici phyton&company😆: intendo proprio vivere della nostra penna, pardón, vivere del nostro mouse:
untitled.gif
La qual cosa però, inutile dirlo, succederebbe soltanto se vivessimo in terra gringa e bussassimo alle porte delle case editrici tradizionali. L'alternativa ci starebbe: i nostri guadagni online probabilmente raggiungerebbero il valore di uno stipendio, anche solo part-time (già nelle latine lande corrisponde al compenso di un trainee) nelle Filippine, dove peraltro non sono obbligati neppure a portarli in dichiarazione dei redditi perchè al governo filippino non gliene frega una cippa delle attività extraterritoriali. L'esatto opposto del mio paese, che non fa che disincentivare con ogni mezzo l'offerta dei servizi fuori dei confini territoriali e desidererebbe che guadagnassimo unicamente in moneta locale. Auguro al governo in atto l'impeachment al più presto (ma soprattutto per il vergognoso scempio del nuovo codice civile che potrebbe essere approvato entro dicembre).

0
0
0.000