I'm having difficulty in determining what the best practices are for structuring data for calling various APIs that contain bitcoin prices. I want to be able to call multiple APIs, without duplicate code.
My initial thought was to build classes for each of the APIs I would be calling, and feed their attributes (api_id, url, and json_tree (json path I'd like to pull data from) to the BtcAPI class, and spit them out.
*Note, before reading that while BtcAPI works, the Coindesk/Bitstamp classes do not yet interact with that class. I want to ask about the way I should do this before I go to the trouble...*
Now, I'm wondering if I shouldn't make them lists, like:
coindesk = ['http://www.something.com', 'coindesk', '["time"]["updated"]']
...and just iterate through each of them. Or dicts, or any variety of other thing. What data structure is indicated here?
I am basically looking for a bit of a code review (since this code isn't working, I don't want to send it to the code review stack) and an understanding of best practices: tell me where you think I'm screwing up horribly, and what I can do to structure this data better? I'm a python and oop noob. I could do this procedurally, but it would be ugly and superfluous. I imagine I'm using classes a bit wrong, too. Insights? Help? Thank you!
Thank you!
import json
import urllib.request
#The BtcAPI class works well when you feed it static variables. It returns json.
class BtcAPI:
def __init__(self, url, api_id):
self.url = url
self.api_id = api_id
def btc_api_call(self):
hdr = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' }
req = urllib.request.Request(url, headers=hdr)
readdata = urllib.request.urlopen(req)
json_data = readdata.read()
json_dict = json.loads(json_data)
return(json_dict)
class Coindesk:
api_id = 'Coindesk'
url = 'https://api.coindesk.com/v1/bpi/currentprice.json'
json_tree = json_dict['time']['updated']
def __init__(self):
self.current_us_price = current_us_price
class Bitstamp:
api_id = 'Bitstamp'
url = 'https://www.bitstamp.net/api/ticker/'
json_tree = json_dict['last']
def __init__(self):
self.current_us_price = current_us_price
coindesk_url = Coindesk()
coindeskoutput = coindesk_url.url
print(coindeskoutput)
If you want a generic piece of code, I would suggest that you dissociate your code and your configuration data into 2 files. This way you can manage your configuration data (URL, JSON attributes you want to retrieve) without having to modify your actual Python code. This is usually considered a good practice but it implies to manage two files instead of one so it can be a bit of a burden if you are on a very small project.
Example in your case, you can have:
conf.ini
Configuration file which would look like this:
[COINDESK]
url: https://api.coindesk.com/v1/bpi/currentprice.json
response: time.updated
[BITSTAMP]
url: https://www.bitstamp.net/api/ticker
response: last
bitcoin_api.py
Your code would look like this:
import configparser
import requests
import os
class BitcoinAPI:
def __init__(self, API):
config = configparser.ConfigParser()
config.read(os.path.dirname(__file__) + '/conf.ini')
self.url = config.get(API, 'url')
self.attribute = config.get(API, 'response')
self.header = {'content-type': 'application/json'}
def get(self):
response = requests.get(self.url, headers=self.header)
response = response.json()
# Browse the response to fetch only the attributes you want
self.attribute = self.attribute.split('.')
depth = len(self.attribute)
for i in range(depth):
response = response[self.attribute[i]]
print(response)
return response
Then you can call you class in your main script:
import bitcoin_api
result = bitcoin_api.BitcoinAPI('COINDESK').get()
result = bitcoin_api.BitcoinAPI('BITSTAMP').get()
Well, the sane way to struct your code would involve super classes (inheritance) and some sort of standardisation (interfaces).
Assuming that I understand you question, you need a standard on how to request the prices from various exchanges.
So consider this structure (of course it's completely draft):
import requests
class BitcoinAPI:
def get_price_usd(self):
raise NotImplementedError
@staticmethod
def generic_unothorized_request(request_method, url, **kwargs):
return getattr(requests, request_method)(url, **kwargs)
class CoinDesk(BitcoinAPI):
url = 'https://api.coindesk.com/v1/bpi/currentprice.json'
def get_price_usd(self):
return self.generic_unothorized_request('get', url)
# process result, bla bla
class Bitstamp(BitcoinAPI):
def get_price_usd(self):
# Implementation of get_price_usd for Bitstamp
return 0.0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With