Website-Suche

Wie man Web-APIs in Python 3 verwendet


Einführung

Eine API, oder AnwendungsProgrammInterface, ermöglicht es Entwicklern, eine App mit einer anderen zu integrieren. Sie legen einige der inneren Abläufe eines Programms in begrenztem Umfang offen.

Sie können APIs verwenden, um Informationen von anderen Programmen abzurufen oder um Dinge zu automatisieren, die Sie normalerweise in Ihrem Webbrowser tun. Manchmal können Sie APIs verwenden, um Dinge zu tun, die Sie auf keine andere Weise tun können. Eine überraschend große Anzahl von Webangeboten bietet webbasierte APIs neben der bekannteren Website oder mobilen App an, darunter Twitter, Facebook, GitHub und DigitalOcean.

Wenn Sie einige Tutorials zum Programmieren in Python 3 durchgearbeitet haben und sich mit der Syntax, der Struktur und einigen eingebauten Funktionen von Python wohlfühlen, können Sie Python-Programme schreiben, die Ihre bevorzugten APIs nutzen.

In diesem Leitfaden erfahren Sie, wie Sie Python mit der DigitalOcean-API verwenden, um Informationen über Ihr DigitalOcean-Konto abzurufen. Dann werden wir uns ansehen, wie Sie das, was Sie gelernt haben, auf die API von GitHub anwenden können.

Wenn du fertig bist, wirst du die Konzepte verstehen, die bei Web-APIs üblich sind, und du wirst einen Schritt-für-Schritt-Prozess und funktionierende Beispielcodes haben, die du verwenden kannst, um APIs von anderen Diensten auszuprobieren.

Voraussetzungen

Bevor Sie mit diesem Leitfaden beginnen, benötigen Sie Folgendes:

  • Eine lokale Entwicklungsumgebung für Python 3. Sie können die Anleitung 'Wie man eine lokale Programmierumgebung für Python 3 installiert und einrichtet' befolgen, um alles zu konfigurieren, was Sie benötigen.
  • Ein Texteditor, mit dem Sie sich wohlfühlen. Wenn Sie noch keinen Favoriten haben, wählen Sie einen mit Syntaxhervorhebung. Notepad++ für Windows, BBEdit für macOS und Sublime Text oder Atom für jede Plattform sind alles gute Optionen.
  • Ein DigitalOcean-Konto und ein API-Schlüssel. Die ersten paar Absätze in 'Wie man die DigitalOcean API v2 benutzt' zeigen, wie man dies tut.

Schritt 1 — Sich mit einer API vertraut machen

Der erste Schritt zur Nutzung einer neuen API besteht darin, die Dokumentation zu finden und sich einen Überblick zu verschaffen. Die DigitalOcean API-Dokumentation beginnt unter https://developers.linux-console.net/. Um APIs für andere Dienste zu finden, suchen Sie nach dem Namen der Seite und “API” – nicht alle Dienste bewerben sie auf ihren Startseiten.

Einige Dienste haben API-Wrapper. Ein API-Wrapper ist Code, den Sie auf Ihrem System installieren, um die APIs in der von Ihnen gewählten Programmiersprache einfacher zu verwenden. Dieser Leitfaden verwendet keine Wrapper, da sie einen Großteil der internen Funktionsweise der APIs verbergen und oft nicht alles offenbaren, was die API kann. Wrapper können großartig sein, wenn Sie schnell etwas erledigen möchten, aber ein solides Verständnis dafür, was die APIs selbst tun können, wird Ihnen helfen zu entscheiden, ob die Wrapper für Ihre Ziele sinnvoll sind.

Zuerst schauen Sie sich die Einführung in die DigitalOcean-API unter https://developers.linux-console.net/documentation/v2/ an und versuchen Sie nur die Grundlagen zu verstehen, wie man eine Anfrage sendet und was man in der Antwort erwarten kann. In diesem Stadium versuchen Sie nur drei Dinge zu lernen:

  1. Wie sieht eine Anfrage aus? Sind sie alle nur URLs? Wie werden die Daten bei detaillierteren Anfragen formatiert? Normalerweise ist es JSON oder Abfrageparameter wie sie ein Webbrowser verwendet, aber einige nutzen XML oder ein benutzerdefiniertes Format.
  2. Wie sieht eine Antwort aus? Die API-Dokumente zeigen Beispielanfragen und -antworten. Wirst du JSON, XML oder eine andere Art von Antwort erhalten?
  3. Was gehört zu den Anfrage- oder Antwort-Headern? Oft beinhalten die Anfrage-Header Ihr Authentifizierungs-Token, und die Antwort-Header liefern aktuelle Informationen über Ihre Nutzung des Dienstes, beispielsweise wie nah Sie an einer Rate-Limitierung sind.

Die DigitalOcean API verwendet HTTP Methoden (manchmal auch Verben genannt), um anzugeben, ob Sie versuchen, vorhandene Informationen zu lesen, neue Informationen zu erstellen oder etwas zu löschen. Dieser Teil der Dokumentation erklärt, welche Methoden verwendet werden und zu welchen Zwecken. Im Allgemeinen ist eine GET-Anfrage einfacher als eine POST-Anfrage, aber bis Sie hiermit fertig sind, werden Sie keinen großen Unterschied bemerken.

Der nächste Abschnitt der API-Dokumentation behandelt, wie der Server auf Ihre Anfragen reagieren wird. Im Allgemeinen gelingt eine Anfrage oder sie schlägt fehl. Wenn sie fehlschlägt, liegt die Ursache entweder an etwas Schlechtem mit der Anfrage oder an einem Problem auf dem Server. Alle diese Informationen werden mit HTTP-Statuscodes kommuniziert, die 3-stellige Zahlen sind, die in Kategorien unterteilt sind.

  • Die 200-Serie bedeutet „Erfolg“ – Ihre Anfrage war gültig, und die Antwort ist das, was logisch daraus folgt.
  • Die 400-Serie bedeutet "schlechte Anfrage" - es war etwas mit der Anfrage falsch, sodass der Server sie nicht so verarbeitet hat, wie Sie es wollten. Häufige Ursachen für HTTP 400-Fehler sind falsch formatierte Anfragen und Authentifizierungsprobleme.
  • Die 500-Serie bedeutet „Serverfehler“ – Ihre Anfrage war vielleicht in Ordnung, aber der Server konnte Ihnen aus Gründen, die außerhalb Ihrer Kontrolle liegen, im Moment keine gute Antwort geben. Diese sollten selten sein, aber Sie müssen sich der Möglichkeit bewusst sein, damit Sie sie in Ihrem Code behandeln können.

Ihr Code sollte immer den HTTP-Statuscode für jede Antwort überprüfen, bevor Sie versuchen, etwas damit zu tun. Wenn Sie dies nicht tun, werden Sie feststellen, dass Sie Zeit mit Fehlersuche mit unvollständigen Informationen verschwenden.

Jetzt, da Sie eine allgemeine Vorstellung davon haben, wie man eine Anfrage sendet und worauf man in der Antwort achten sollte, ist es Zeit, diese erste Anfrage zu senden.

Schritt 2 — Informationen von der Web-API abrufen

Ihr DigitalOcean-Konto enthält einige administrative Informationen, die Sie möglicherweise nicht in der Weboberfläche gesehen haben. Eine API kann Ihnen eine andere Sicht auf vertraute Informationen bieten. Allein das Betrachten dieser alternativen Ansicht kann manchmal Ideen hervorrufen, was Sie mit einer API tun möchten, oder Dienstleistungen und Optionen offenbaren, von denen Sie nichts wussten.

Lass uns damit beginnen, ein Projekt für unsere Skripte zu erstellen. Erstelle ein neues Verzeichnis für das Projekt mit dem Namen apis:

  1. mkdir apis

Navigiere dann in dieses neue Verzeichnis:

  1. cd apis

Erstellen Sie eine neue virtuelle Umgebung für dieses Projekt:

  1. python3 -m venv apis

Aktivieren Sie die virtuelle Umgebung:

  1. source apis/bin/activate

Installieren Sie dann die Requests-Bibliothek, die wir in unseren Skripten verwenden werden, um HTTP-Anfragen zu stellen:

  1. pip install requests

Mit der konfigurierten Umgebung erstellen Sie eine neue Python-Datei namens do_get_account.py und öffnen Sie sie in Ihrem Texteditor. Beginnen Sie dieses Programm, indem Sie Bibliotheken für die Arbeit mit JSON und HTTP-Anfragen importieren.

import json
import requests

Diese import-Anweisungen laden Python-Code, der es uns ermöglicht, mit dem JSON-Datenformat und dem HTTP-Protokoll zu arbeiten. Wir verwenden diese Bibliotheken, weil wir uns nicht für die Einzelheiten interessieren, wie man HTTP-Anfragen sendet oder wie man gültiges JSON analysiert und erstellt; wir möchten sie einfach nutzen, um diese Aufgaben zu erledigen. Alle unsere Skripte in diesem Tutorial werden so beginnen.

Als nächstes möchten wir einige Variablen einrichten, um Informationen zu speichern, die in jeder Anfrage gleich sein werden. Dies erspart uns, sie immer wieder einzugeben, und gibt uns einen zentralen Ort, um Aktualisierungen vorzunehmen, falls sich etwas ändert. Fügen Sie diese Zeilen nach den import-Anweisungen in die Datei ein.

...
api_token = 'your_api_token'
api_url_base = 'https://api.linux-console.net/v2/'

Die api_token Variable ist ein String, der Ihr DigitalOcean API-Token enthält. Ersetzen Sie den Wert im Beispiel durch Ihr eigenes Token. Die api_url_base Variable ist der String, der jede URL in der DigitalOcean API beginnt. Wir werden später im Code nach Bedarf daran anhängen.

Als nächstes müssen wir die HTTP-Anforderungsheader so einrichten, wie es in den API-Dokumenten beschrieben ist. Fügen Sie diese Zeilen zur Datei hinzu, um ein Wörterbuch mit Ihren Anforderungsheadern einzurichten:

...
headers = {'Content-Type': 'application/json',
           'Authorization': 'Bearer {0}'.format(api_token)}

Dies setzt zwei Header gleichzeitig. Der Content-Type-Header sagt dem Server, dass er JSON-formatierten Daten im Body der Anfrage erwarten soll. Der Authorization-Header muss unser Token enthalten, daher verwenden wir die String-Formatierungslogik von Python, um unsere api_token-Variable in den String einzufügen, während wir den String erstellen. Wir hätten das Token hier als literalen String einfügen können, aber die Trennung macht mehrere Dinge in der Zukunft einfacher:

  • Wenn Sie das Token ersetzen müssen, ist es einfacher zu erkennen, wo Sie das tun müssen, wenn es eine separate Variable ist.
  • Wenn du deinen Code mit jemandem teilen möchtest, ist es einfacher, deinen API-Token zu entfernen, und es ist einfacher für deinen Freund zu sehen, wo er seinen einsetzen kann.
  • Es ist selbstdokumentierend. Wenn das API-Token nur als Stringliteral verwendet wird, dann versteht jemand, der Ihren Code liest, möglicherweise nicht, was er sich anschaut.

Jetzt, wo wir diese Einrichtungshinweise behandelt haben, ist es an der Zeit, die Anfrage tatsächlich zu senden. Ihre Neigung könnte sein, einfach zu beginnen, die Anfragen zu erstellen und zu senden, aber es gibt eine bessere Methode. Wenn Sie diese Logik in eine Funktion einfügen, die das Senden der Anfrage und das Lesen der Antwort behandelt, müssen Sie etwas klarer darüber nachdenken, was Sie tun. Sie werden auch Code haben, der das Testen und die Wiederverwendung erleichtert. Das ist es, was wir tun werden.

Diese Funktion verwendet die Variablen, die Sie erstellt haben, um die Anfrage zu senden und die Kontoinformationen in einem Python-Wörterbuch zurückzugeben.

Um die Logik in dieser frühen Phase klar zu halten, werden wir noch keine detaillierte Fehlerbehandlung durchführen, aber wir werden das bald hinzufügen.

Definiere die Funktion, die die Kontoinformationen abruft. Es ist immer eine gute Idee, eine Funktion nach dem zu benennen, was sie tut: Diese hier ruft Kontoinformationen ab, also nennen wir sie get_account_info:

...
def get_account_info():
  
    api_url = '{0}account'.format(api_url_base)

    response = requests.get(api_url, headers=headers)
    
    if response.status_code == 200:
        return json.loads(response.content.decode('utf-8'))
    else:
        return None

Wir erstellen den Wert für api_url mithilfe der String-Formatierungsmethode von Python, ähnlich wie wir es in den Headern verwendet haben; wir fügen die Basis-URL der API vor dem String account hinzu, um die URL https://api.linux-console.net/v2/account zu erhalten, die die Kontoinformationen zurückgeben sollte.

Die response Variable enthält ein Objekt, das vom Python requests Modul erstellt wurde. Diese Zeile sendet die Anfrage an die URL, die wir mit den am Anfang des Skripts definierten Headern erstellt haben, und gibt die Antwort von der API zurück.

Als Nächstes betrachten wir den HTTP-Statuscode der Antwort.

Wenn es 200 ist, eine erfolgreiche Antwort, dann verwenden wir die json-Moduls loads-Funktion, um einen String als JSON zu laden. Der String, den wir laden, ist der Inhalt des response-Objekts, response.content. Der Teil .decode('utf-8') sagt Python, dass dieser Inhalt mit dem UTF-8-Zeichensatz codiert ist, was bei allen Antworten von der DigitalOcean-API der Fall sein wird. Das json-Modul erstellt daraus ein Objekt, das wir als Rückgabewert für diese Funktion verwenden.

Wenn die Antwort nicht 200 war, geben wir None zurück, was ein spezieller Wert in Python ist, den wir überprüfen können, wenn wir diese Funktion aufrufen. Sie werden bemerken, dass wir zu diesem Zeitpunkt einfach alle Fehler ignorieren. Dies dient dazu, die “Erfolg”-Logik klar zu halten. Wir werden bald umfassendere Fehlerüberprüfungen hinzufügen.

Rufe jetzt diese Funktion auf, überprüfe, ob sie eine gute Antwort erhalten hat, und gib die Details aus, die die API zurückgegeben hat:

...
account_info = get_account_info()

if account_info is not None:
    print("Here's your info: ")
    for k, v in account_info['account'].items():
        print('{0}:{1}'.format(k, v))
    
else:
    print('[!] Request Failed')

account_info=get_account_info() setzt die Variable account_info auf das, was aus dem Aufruf von get_account_info() zurückgekommen ist, sodass es entweder der spezielle Wert None oder die Sammlung von Informationen über das Konto sein wird.

Wenn es nicht None ist, dann geben wir jedes Stück Information in seiner eigenen Zeile aus, indem wir die items()-Methode verwenden, die alle Python-Dictionaries haben.

Andernfalls (das heißt, wenn account_info None ist), drucken wir eine Fehlermeldung aus.

Lass uns hier für einen Moment pausieren. Diese if-Anweisung mit dem doppelten Negativ mag zunächst awkward erscheinen, aber sie ist ein gängiges Python-Idiom. Ihr Vorteil besteht darin, dass der Code, der im Erfolgsfall ausgeführt wird, sehr nah an der Bedingung gehalten wird, anstatt nach der Behandlung von Fehlerfällen.

Du kannst es auch andersrum machen, wenn du das bevorzugst, und es könnte eine gute Übung sein, diesen Code tatsächlich selbst zu schreiben. Anstatt if account_info is not None: könntest du mit if account_info is None: beginnen und sehen, wie der Rest sich fügt.

Speichern Sie das Skript und probieren Sie es aus:

  1. python do_get_account.py

Die Ausgabe wird ungefähr so aussehen:

Here's your info: 
droplet_limit:25
email:sammy@linux-console.net
status:active
floating_ip_limit:3
email_verified:True
uuid:123e4567e89b12d3a456426655440000
status_message:

Du weißt jetzt, wie man Daten von einer API abruft. Als Nächstes werden wir zu etwas Interessanterem übergehen – der Verwendung einer API, um Daten zu ändern.

Schritt 3 — Ändern von Informationen auf dem Server

Nachdem Sie mit einer schreibgeschützten Anfrage geübt haben, ist es Zeit, Änderungen vorzunehmen. Lassen Sie uns dies erkunden, indem wir Python und die DigitalOcean API verwenden, um einen SSH-Schlüssel zu Ihrem DigitalOcean-Konto hinzuzufügen.

Zuerst sollten Sie die API-Dokumentation für SSH-Schlüssel einsehen, die unter https://developers.linux-console.net/documentation/v2/#ssh-keys verfügbar ist.

Die API ermöglicht es Ihnen, die aktuellen SSH-Schlüssel auf Ihrem Konto aufzulisten und auch neue hinzuzufügen. Die Anfrage zum Abrufen einer Liste von SSH-Schlüsseln ähnelt derjenigen zum Abrufen von Kontoinformationen. Die Antwort ist jedoch anders: Im Gegensatz zu einem Konto können Sie null, einen oder viele SSH-Schlüssel haben.

Erstellen Sie eine neue Datei für dieses Skript mit dem Namen do_ssh_keys.py und beginnen Sie sie genau wie die letzte. Importieren Sie die Module json und requests, damit Sie sich nicht um die Einzelheiten von JSON oder dem HTTP-Protokoll kümmern müssen. Fügen Sie dann Ihr DigitalOcean API-Token als Variable hinzu und richten Sie die Anfrage-Header in einem Dictionary ein.

import json
import requests


api_token = 'your_api_token'
api_url_base = 'https://api.linux-console.net/v2/'
headers = {'Content-Type': 'application/json',
           'Authorization': 'Bearer {0}'.format(api_token)}

Die Funktion, die wir erstellen werden, um die SSH-Schlüssel zu erhalten, ist ähnlich derjenigen, die wir verwendet haben, um Kontoinformationen zu erhalten, aber dieses Mal werden wir Fehler direkter behandeln.

Zuerst werden wir den API-Aufruf durchführen und die Antwort in einer response Antwortvariable speichern. Die api_url wird jedoch nicht die gleiche sein wie im vorherigen Skript; dieses Mal muss sie auf https://api.linux-console.net/v2/account/keys zeigen.

Fügen Sie diesen Code zum Skript hinzu:

...
def get_ssh_keys():
  
    api_url = '{0}account/keys'.format(api_url_base)

    response = requests.get(api_url, headers=headers)

Jetzt fügen wir eine Fehlerbehandlung hinzu, indem wir den HTTP-Statuscode in der Antwort betrachten. Wenn es 200 ist, geben wir den Inhalt der Antwort als Dictionary zurück, genau wie zuvor. Wenn es etwas anderes ist, drucken wir eine hilfreiche Fehlermeldung aus, die mit der Art des Statuscodes verbunden ist, und geben dann None zurück.

Fügen Sie diese Zeilen zur get_ssh_keys-Funktion hinzu:

...

    if response.status_code >= 500:
        print('[!] [{0}] Server Error'.format(response.status_code))
        return None
    elif response.status_code == 404:
        print('[!] [{0}] URL not found: [{1}]'.format(response.status_code,api_url))
        return None  
    elif response.status_code == 401:
        print('[!] [{0}] Authentication Failed'.format(response.status_code))
        return None
    elif response.status_code == 400:
        print('[!] [{0}] Bad Request'.format(response.status_code))
        return None
    elif response.status_code >= 300:
        print('[!] [{0}] Unexpected Redirect'.format(response.status_code))
        return None
    elif response.status_code == 200:
        ssh_keys = json.loads(response.content.decode('utf-8'))
        return ssh_keys
    else:
        print('[?] Unexpected Error: [HTTP {0}]: Content: {1}'.format(response.status_code, response.content))
    return None

Dieser Code behandelt sechs verschiedene Fehlerbedingungen, indem er den HTTP-Statuscode in der Antwort überprüft.

  • Ein Code von 500 oder höher weist auf ein Problem auf dem Server hin. Diese sollten selten sein und werden nicht durch Probleme mit der Anfrage verursacht, daher drucken wir nur den Statuscode aus.
  • Ein Code von 404 bedeutet "nicht gefunden", was wahrscheinlich auf einen Tippfehler in der URL zurückzuführen ist. Für diesen Fehler drucken wir den Statuscode und die URL aus, die dazu geführt hat, damit Sie sehen können, warum es fehlgeschlagen ist.
  • Ein Code von 401 bedeutet, dass die Authentifizierung fehlgeschlagen ist. Der wahrscheinlichste Grund dafür ist ein falscher oder fehlender api_key.
  • Ein Code im Bereich 300 zeigt eine Weiterleitung an. Die DigitalOcean-API verwendet keine Weiterleitungen, daher sollte dies niemals vorkommen, aber während wir Fehler behandeln, schadet es nicht, zu überprüfen. Viele Fehler werden durch Dinge verursacht, von denen der Programmierer dachte, dass sie niemals passieren sollten.
  • Ein Code von 200 bedeutet, dass die Anfrage erfolgreich bearbeitet wurde. Dafür drucken wir nichts aus. Wir geben einfach die SSH-Schlüssel als JSON-Objekt zurück, wobei wir die gleiche Syntax verwenden, die wir im vorherigen Skript benutzt haben.
  • Wenn der Antwortcode etwas anderes war, geben wir den Statuscode als "unerwarteten Fehler" aus.

Das sollte alle Fehler behandeln, die wir wahrscheinlich beim Aufruf der API erhalten. An diesem Punkt haben wir entweder eine Fehlermeldung und das None-Objekt oder wir haben Erfolg und ein JSON-Objekt, das null oder mehr SSH-Schlüssel enthält. Unser nächster Schritt ist es, sie auszudrucken:

...

ssh_keys = get_ssh_keys()

if ssh_keys is not None:
    print('Here are your keys: ')
    for key, details in enumerate(ssh_keys['ssh_keys']):
        print('Key {}:'.format(key))
        for k, v in details.items():
            print('  {0}:{1}'.format(k, v))
else:
    print('[!] Request Failed')

Da die Antwort eine Liste (oder ein Array) von SSH-Schlüsseln enthält, wollen wir die gesamte Liste durchlaufen, um alle Schlüssel zu sehen. Wir verwenden die enumerate-Methode von Python dafür. Dies ähnelt der items-Methode, die für Dictionaries verfügbar ist, funktioniert jedoch stattdessen mit Listen.

Wir verwenden enumerate und nicht nur eine for-Schleife, weil wir wissen möchten, wie weit wir in der Liste für einen bestimmten Schlüssel sind.

Die Informationen zu jedem Schlüssel werden als ein Wörterbuch zurückgegeben, daher verwenden wir denselben for k,v in details.items(): Code, den wir im vorherigen Skript für das Konto-Informations-Wörterbuch verwendet haben.

Führen Sie dieses Skript aus und Sie erhalten eine Liste der SSH-Schlüssel, die bereits mit Ihrem Konto verknüpft sind.

  1. python get_ssh_keys.py

Die Ausgabe wird ungefähr so aussehen, abhängig davon, wie viele SSH-Schlüssel Sie bereits in Ihrem Konto haben.

Here are your keys: 
Kcy 0:
  id:280518
  name:work
  fingerprint:96:f7:fb:9f:60:9c:9b:f9:a9:95:01:5c:5c:2c:d5:a0
  public_key:ssh-rsa AAAAB5NzaC1yc2cAAAADAQABAAABAQCwgr9Fzc/YTD/V2Ka5I52Rx4I+V2Ka5I52Rx4Ir5LKSCqkQ1Cub+... sammy@work
Kcy 1:
  id:290536
  name:home
  fingerprint:90:1c:0b:ac:fa:b0:25:7c:af:ab:c5:94:a5:91:72:54
  public_key:ssh-rsa AAAAB5NzaC1yc2cAAAABJQAAAQcAtTZPZmV96P9ziwyr5LKSCqkQ1CubarKfK5r7iNx0RNnlJcqRUqWqSt... sammy@home

Jetzt, da Sie die SSH-Schlüssel in Ihrem Konto auflisten können, wird Ihr letztes Skript hier eines sein, das einen neuen Schlüssel zur Liste hinzufügt.

Bevor wir einen neuen SSH-Schlüssel hinzufügen können, müssen wir einen erstellen. Für eine ausführlichere Behandlung dieses Schrittes werfen Sie einen Blick auf das Tutorial "Wie man SSH-Schlüssel einrichtet".

Für unsere Zwecke benötigen wir jedoch nur einen einfachen Schlüssel. Führen Sie diesen Befehl aus, um einen neuen unter Linux, BSD oder MacOS zu generieren. Sie können dies auch auf einem bestehenden Droplet tun, wenn Sie möchten.

  1. ssh-keygen -t rsa

Wenn Sie dazu aufgefordert werden, geben Sie die Datei ein, um den Schlüssel zu speichern, und geben Sie kein Passwort an.

Generating public/private rsa key pair.
Enter file in which to save the key (/home/sammy/.ssh/id_rsa): /home/sammy/.ssh/sammy 
Created directory '/home/sammy/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/sammy/.ssh/sammy.
Your public key has been saved in /home/sammy/.ssh/sammy.pub.
...

Beachte, wo die Datei mit dem öffentlichen Schlüssel gespeichert wurde, da du sie für das Skript benötigst.

Erstelle ein neues Python-Skript und nenne es add_ssh_key.py, und starte es wie die anderen:

import json
import requests


api_token = 'your_api_token'
api_url_base = 'https://api.linux-console.net/v2/'
headers = {'Content-Type': 'application/json',
           'Authorization': 'Bearer {0}'.format(api_token)}

Wir werden eine Funktion verwenden, um unsere Anfrage zu stellen, aber diese wird etwas anders sein.

Erstellen Sie eine Funktion namens add_ssh_key, die zwei Argumente akzeptiert: den Namen, der für den neuen SSH-Schlüssel verwendet werden soll, und den Dateinamen des Schlüssels selbst auf Ihrem lokalen System. Die Funktion wird die Datei lesen und eine HTTP POST-Anfrage anstelle einer GET-Anfrage senden:

...

def add_ssh_key(name, filename):
  
    api_url = '{0}account/keys'.format(api_url_base)
    
    with open(filename, 'r') as f:
        ssh_key = f.readline()

    ssh_key = {'name': name, 'public_key': ssh_key}
    
    response = requests.post(api_url, headers=headers, json=ssh_key)

Die Zeile with open(filename, 'r') as f: öffnet die Datei im Nur-Lese-Modus, und die folgende Zeile liest die erste (und einzige) Zeile aus der Datei und speichert sie in der Variable ssh_key.

Als nächstes erstellen wir ein Python-Wörterbuch mit dem Namen ssh_key, das die Namen und Werte enthält, die die API erwartet.

Wenn wir die Anfrage senden, gibt es jedoch ein wenig mehr, was neu ist. Es ist ein POST anstelle eines GET, und wir müssen den ssh_key im Body der POST-Anfrage senden, kodiert als JSON. Das requests-Modul kümmert sich um die Details für uns; requests.post sagt ihm, dass es die POST-Methode verwenden soll, und die Angabe von json=ssh_key sagt ihm, dass die Variable ssh_key im Body der Anfrage, kodiert als JSON, gesendet werden soll.

Laut der API wird die Antwort bei Erfolg HTTP 201 anstelle von 200 sein, und der Antwortkörper wird die Details des Schlüssels enthalten, den wir gerade hinzugefügt haben.

Fügen Sie den folgenden Fehlerbehandlungs-Code zur Funktion add_ssh_key hinzu. Er ist ähnlich dem vorherigen Skript, außer dass wir diesmal nach dem Code 201 statt 200 für den Erfolg suchen müssen:

...
    if response.status_code >= 500:
        print('[!] [{0}] Server Error'.format(response.status_code))
        return None
    elif response.status_code == 404:
        print('[!] [{0}] URL not found: [{1}]'.format(response.status_code,api_url))
        return None
    elif response.status_code == 401:
        print('[!] [{0}] Authentication Failed'.format(response.status_code))
        return None
    elif response.status_code >= 400:
        print('[!] [{0}] Bad Request'.format(response.status_code))
        print(ssh_key )
        print(response.content )
        return None
    elif response.status_code >= 300:
        print('[!] [{0}] Unexpected redirect.'.format(response.status_code))
        return None
    elif response.status_code == 201:
        added_key = json.loads(response.content)
        return added_key
    else:
        print('[?] Unexpected Error: [HTTP {0}]: Content: {1}'.format(response.status_code, response.content))
        return None

Diese Funktion gibt, wie die vorherigen, entweder None oder den Antwortinhalt zurück, sodass wir denselben Ansatz wie zuvor verwenden, um das Ergebnis zu überprüfen.

Als Nächstes rufen Sie die Funktion auf und verarbeiten das Ergebnis. Übergeben Sie den Pfad zu Ihrem neu erstellten SSH-Schlüssel als zweites Argument:

...
add_response = add_ssh_key('tutorial_key', '/home/sammy/.ssh/sammy.pub')

if add_response is not None:
    print('Your key was added: ' )
    for k, v in add_response.items():
        print('  {0}:{1}'.format(k, v))
else:
    print('[!] Request Failed')

Führen Sie dieses Skript aus und Sie erhalten eine Rückmeldung, dass Ihr neuer Schlüssel hinzugefügt wurde.

  1. python add_ssh_key.py

Die Ausgabe wird ungefähr so aussehen:

Your key was added: 
  ssh_key:{'id': 9458326, 'name': 'tutorial_key', 'fingerprint': '64:76:37:77:c8:c7:26:05:f5:7b:6b:e1:bb:d6:80:da', 'public_key': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCUtY9aizEcVJ65/O5CE6tY8Xodrkkdh9BB0GwEUE7eDKtTh4NAxVjXc8XdzCLKtdMwfSg9xwxSi3axsVWYWBUhiws0YRxxMNTHCBDsLFTJgCFC0JCmSLB5ZEnKl+Wijbqnu2r8k2NoXW5GUxNVwhYztXZkkzEMNT78TgWBjPu2Tp1qKREqLuwOsMIKt4bqozL/1tu6oociNMdLOGUqXNrXCsOIvTylt6ROF3a5UnVPXhgz0qGbQrSHvCEfuKGZ1kw8PtWgeIe7VIHbS2zTuSDCmyj1Nw1yOTHSAqZLpm6gnDo0Lo9OEA7BSFr9W/VURmTVsfE1CNGSb6c6SPx0NpoN sammy@tutorial-test'}

Wenn Sie vergessen haben, die "Erfolg"-Bedingung so zu ändern, dass nach HTTP 201 anstelle von 200 gesucht wird, wird ein Fehler gemeldet, aber der Schlüssel wurde trotzdem hinzugefügt. Ihre Fehlerbehandlung hätte Ihnen mitgeteilt, dass der Statuscode 201 war. Sie sollten dies als Mitglied der 200-Serie erkennen, die Erfolg anzeigt. Dies ist ein Beispiel dafür, wie grundlegende Fehlerbehandlung die Fehlersuche vereinfachen kann.

Sobald Sie den Schlüssel erfolgreich mit diesem Skript hinzugefügt haben, führen Sie es erneut aus, um zu sehen, was passiert, wenn Sie versuchen, einen bereits vorhandenen Schlüssel hinzuzufügen.

Die API wird eine HTTP 422 Antwort zurücksenden, die Ihr Skript in eine Nachricht übersetzt, die sagt: „SSH-Schlüssel wird bereits in Ihrem Konto verwendet.“

[!] [422] Bad Request
{'name': 'tutorial_key', 'public_key': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCUtY9aizEcVJ65/O5CE6tY8Xodrkkdh9BB0GwEUE7eDKtTh4NAxVjXc8XdzCLKtdMwfSg9xwxSi3axsVWYWBUhiws0YRxxMNTHCBDsLFTJgCFC0JCmSLB5ZEnKl+Wijbqnu2r8k2NoXW5GUxNVwhYztXZkkzEMNT78TgWBjPu2Tp1qKREqLuwOsMIKt4bqozL/1tu6oociNMdLOGUqXNrXCsOIvTylt6ROF3a5UnVPXhgz0qGbQrSHvCEfuKGZ1kw8PtWgeIe7VIHbS2zTuSDCmyj1Nw1yOTHSAqZLpm6gnDo0Lo9OEA7BSFr9W/VURmTVsfE1CNGSb6c6SPx0NpoN sammy@tutorial-test'}
b'{"id":"unprocessable_entity","message":"SSH Key is already in use on your account"}'
[!] Request Failed

Führen Sie nun Ihr get_ssh_keys.py Skript erneut aus und Sie werden Ihren neu hinzugefügten Schlüssel in der Liste sehen.

Mit kleinen Modifikationen könnten diese beiden Skripte eine schnelle Möglichkeit sein, neue SSH-Schlüssel zu Ihrem DigitalOcean-Konto hinzuzufügen, wann immer Sie es benötigen. Verwandte Funktionen in dieser API ermöglichen es Ihnen, einen bestimmten Schlüssel umzubenennen oder zu löschen, indem Sie seine einzigartige Schlüssel-ID oder seinen Fingerabdruck verwenden.

Lass uns eine andere API anschauen und sehen, wie die Fähigkeiten, die du gerade gelernt hast, umgesetzt werden.

Schritt 4 — Arbeiten mit einer anderen API

GitHub hat ebenfalls eine API. Alles, was Sie über die Verwendung der DigitalOcean API gelernt haben, ist direkt auf die Verwendung der GitHub API anwendbar.

Mach dich mit der GitHub-API vertraut, so wie du es mit DigitalOcean getan hast. Suche nach der API-Dokumentation und überfliege den Überblick-Bereich. Du wirst sofort sehen, dass die GitHub-API und die DigitalOcean-API einige Ähnlichkeiten aufweisen.

Zuerst werden Sie feststellen, dass es einen gemeinsamen Stamm für alle API-URLs gibt: https://api.github.com/. Sie wissen, wie Sie das als Variable in Ihrem Code verwenden können, um den Prozess zu optimieren und das Potenzial für Fehler zu verringern.

Die API von GitHub verwendet JSON als ihr Anfrage- und Antwortformat, genau wie es DigitalOcean tut, sodass du weißt, wie man diese Anfragen stellt und die Antworten verarbeitet.

Antworten enthalten Informationen über die Ratenbegrenzungen in den HTTP-Antwort-Headern, wobei fast die gleichen Namen und exakt die gleichen Werte wie bei DigitalOcean verwendet werden.

GitHub verwendet OAuth zur Authentifizierung, und Sie können Ihr Token in einem Anfrage-Header senden. Die Details dieses Tokens sind ein wenig anders, aber die Art und Weise, wie es verwendet wird, ist identisch mit der, die Sie mit der API von DigitalOcean verwendet haben.

Es gibt auch einige Unterschiede. GitHub empfiehlt die Verwendung eines Anfrage-Headers, um die Version der API anzugeben, die Sie verwenden möchten. Sie wissen, wie man Header zu Anfragen in Python hinzufügt.

GitHub möchte auch, dass Sie eine eindeutige User-Agent-Zeichenfolge in den Anfragen verwenden, damit sie Sie leichter finden können, wenn Ihr Code Probleme verursacht. Dies würden Sie ebenfalls mit einem Header behandeln.

Die GitHub-API verwendet die gleichen HTTP-Anforderungsmethoden, verwendet jedoch auch eine neue, die PATCH genannt wird, für bestimmte Operationen. Die GitHub-API verwendet GET, um Informationen zu lesen, POST, um ein neues Element hinzuzufügen, und PATCH, um ein vorhandenes Element zu ändern. Diese PATCH-Anforderung ist die Art von Dingen, auf die du in der API-Dokumentation achten solltest.

Nicht alle GitHub-API-Aufrufe erfordern eine Authentifizierung. Zum Beispiel können Sie eine Liste der Repositories eines Benutzers abrufen, ohne ein Zugriffstoken zu benötigen. Lassen Sie uns ein Skript erstellen, um diese Anfrage zu stellen und die Ergebnisse anzuzeigen.

Wir werden die Fehlerbehandlung in diesem Skript vereinfachen und nur eine Anweisung verwenden, um alle möglichen Fehler zu behandeln. Man muss nicht immer Code haben, um jede Art von Fehler separat zu behandeln, aber es ist eine gute Gewohnheit, etwas mit Fehlerbedingungen zu tun, wenn es nur darum geht, sich daran zu erinnern, dass die Dinge nicht immer so laufen, wie man es erwartet.

Erstellen Sie eine neue Datei mit dem Namen github_list_repos.py in Ihrem Editor und fügen Sie den folgenden Inhalt hinzu, der Ihnen wahrscheinlich ziemlich vertraut vorkommt:

import json
import requests


api_url_base = 'https://api.github.com/'
headers = {'Content-Type': 'application/json',
           'User-Agent': 'Python Student',
           'Accept': 'application/vnd.github.v3+json'}

Die Importe sind die gleichen, die wir verwendet haben. Die api_url_base ist der Punkt, an dem alle GitHub APIs beginnen.

Die Header umfassen zwei der optionalen, die GitHub in seiner Übersicht erwähnt, sowie den, der besagt, dass wir JSON-formatierten Daten in unserer Anfrage senden.

Auch wenn dies ein kleines Skript ist, werden wir trotzdem eine Funktion definieren, um unsere Logik modular zu halten und die Logik für die Anfrage zu kapseln. Oft wachsen deine kleinen Skripte zu größeren heran, daher ist es hilfreich, dabei gewissenhaft zu sein. Füge eine Funktion namens get_repos hinzu, die einen Benutzernamen als Argument akzeptiert:

...
def get_repos(username):

    api_url = '{}orgs/{}/repos'.format(api_url_base, username)

    response = requests.get(api_url, headers=headers)

    if response.status_code == 200:
        return (response.content)
    else:
        print('[!] HTTP {0} calling [{1}]'.format(response.status_code, api_url))
        return None

Innerhalb der Funktion bauen wir die URL aus der api_url_base, dem Namen des Benutzers, für den wir uns interessieren, und den statischen Teilen der URL, die GitHub mitteilen, dass wir die Repository-Liste wünschen. Dann überprüfen wir den HTTP-Statuscode der Antwort, um sicherzustellen, dass er 200 (Erfolg) war. Wenn es erfolgreich war, geben wir den Antwortinhalt zurück. Wenn nicht, geben wir den tatsächlichen Statuscode und die gebaute URL aus, damit wir eine Vorstellung davon haben, wo wir möglicherweise einen Fehler gemacht haben.

Jetzt rufen Sie die Funktion auf und übergeben den GitHub-Benutzernamen, den Sie verwenden möchten. Wir verwenden octokit für dieses Beispiel. Dann drucken Sie die Ergebnisse auf den Bildschirm:

...
repo_list = get_repos('octokit')

if repo_list is not None:
    print(repo_list)
else:
    print('No Repo List Found')

Speichern Sie die Datei und führen Sie das Skript aus, um die Repositories für den von Ihnen angegebenen Benutzer anzuzeigen.

  1. python github_list_repos.py

Sie werden eine Menge Daten in der Ausgabe sehen, da wir die Antwort in diesem Beispiel nicht als JSON geparst haben und auch die Ergebnisse nicht auf spezifische Schlüssel gefiltert haben. Nutzen Sie, was Sie in den anderen Skripten gelernt haben, um das zu tun. Sehen Sie sich die Ergebnisse an, die Sie erhalten, und prüfen Sie, ob Sie den Namen des Repositories ausgeben können.

Eine schöne Sache an diesen GitHub-APIs ist, dass Sie auf die Anfragen, für die Sie keine Authentifizierung benötigen, direkt in Ihrem Webbrowser zugreifen können. Dies ermöglicht es Ihnen, die Antworten mit dem zu vergleichen, was Sie in Ihren Skripten sehen. Versuchen Sie, https://api.github.com/orgs/octokit/repos in Ihrem Browser zu besuchen, um die dortige Antwort zu sehen.

Inzwischen wissen Sie, wie Sie die Dokumentation lesen und den notwendigen Code schreiben, um spezifischere Anfragen zu senden, die Ihre eigenen Ziele mit der GitHub API unterstützen.

Den vollständigen Code für alle Beispiele in diesem Tutorial finden Sie in diesem Repository auf GitHub.

Schlussfolgerung

In diesem Tutorial haben Sie gelernt, wie man Web-APIs für zwei verschiedene Dienste mit leicht unterschiedlichen Stilen verwendet. Sie haben die Bedeutung des Einfügens von Fehlerbehandlungs-Code erkannt, um das Debuggen zu erleichtern und die Skripte robuster zu machen. Sie haben die Python-Module requests und json verwendet, um sich von den Details dieser Technologien zu isolieren und einfach Ihre Arbeit zu erledigen, und Sie haben die Verarbeitung von Anfrage und Antwort in einer Funktion gekapselt, um Ihre Skripte modularer zu gestalten.

Und noch dazu haben Sie jetzt einen wiederholbaren Prozess, dem Sie folgen können, wenn Sie eine neue Web-API lernen:

  1. Finde die Dokumentation und lies die Einleitung, um die Grundlagen des Umgangs mit der API zu verstehen.
  2. Hol dir ein Authentifizierungstoken, wenn du eins brauchst, und schreibe ein modulares Skript mit grundlegender Fehlerbehandlung, um eine einfache Anfrage zu senden, auf Fehler zu reagieren und die Antwort zu verarbeiten.
  3. Erstellen Sie die Anfragen, die Ihnen die Informationen beschaffen, die Sie von dem Dienst möchten.

Festigen Sie jetzt dieses neu gewonnene Wissen und finden Sie eine andere API, die Sie verwenden können, oder sogar eine weitere Funktion einer der APIs, die Sie hier verwendet haben. Ein eigenes Projekt wird Ihnen helfen, das, was Sie hier gelernt haben, zu festigen.