بکندباز

نحوه ایجاد API در پایتون

ساخت api در پایتون

به عنوان یک فعال علوم داده، بارها مجبوریم کار خود را به اشتراک بگذاریم تا هر کس دیگری در شرکت بتواند از فرآیندها یا مدل هایی که ما ایجاد کرده ایم استفاده کند. واضح است که اشتراک‌گذاری اسکریپت گزینه مناسبی نیست، زیرا همه به کد شما دسترسی پیدا خواهند کرد. در چنین زمانی است که API ها وارد عمل می شوند. امروز، قصد داریم ببینیم API چیست و چگونه یک API در پایتون ایجاد کنیم.

مبانی API

یک API (Application Programming Interface) به دو سیستم کامپیوتری اجازه می دهد تا با یکدیگر تعامل داشته باشند. به عنوان مثال، اگر یک اتوماسیون ایجاد کنیم که یک گزارش تولید می کند و آن را با ایمیل ارسال می کند، ارسال آن ایمیل به صورت دستی انجام نمی شود، خود اسکریپت این کار را انجام می دهد. برای انجام این کار، پایتون (یا زبانی که ما استفاده می‌کنیم)، باید از جی‌میل بخواهد که آن ایمیل را ارسال کند و آن گزارش به افراد خاصی پیوست شود. راه انجام آن از طریق یک API، (در این مورد API Gmail) است.

خوب، اکنون که می دانید API چیست، بیایید ببینیم که بخش های اصلی یک API چیست:

  • پروتکل انتقال HTTP : راه اصلی انتقال اطلاعات در وب است. روش های مختلفی وجود دارد که هر یک از آنها برای مسائل مختلف استفاده می شود:
    • GET : این روش اجازه می دهد تا اطلاعات را از پایگاه داده یا از یک کد دیگر بدست آورید.
    • POST : به شما امکان می دهد اطلاعات را ارسال کنید، مثلاً برای افزودن اطلاعات به پایگاه داده یا ارسال ورودی یک مدل یادگیری ماشینی.
    • PUT: به شما امکان می دهد اطلاعات را به روز کنید. معمولاً برای مدیریت اطلاعات در پایگاه داده استفاده می شود.
    • DELETE : از این روش برای حذف اطلاعات از پایگاه داده استفاده می شود.
  • URL : آدرس API. اساساً این URL از سه بخش تشکیل شده است:
    • پروتکل : مانند هر آدرسی، می تواند http://یا https://باشد.
    • دامنه : میزبانی که اسکریپت مربوط به API روی آن میزبانی می شود. به عنوان مثال، در وب سایت من، دامنه api.backendbaz.ir.
    • نقطه پایانی : مانند یک وب سایت که دارای چندین صفحه (/ blog)، (/ terms) است، API نیز می تواند چندین صفحه را شامل شود و هر کدام کارهای متفاوتی انجام می دهند. هنگامی که API خود را در پایتون ایجاد می کنیم، باید مطمئن شویم که هر نقطه پایانی نماینده کاری است که API پشت آن انجام می دهد.

خوب، حالا که می دانیم API چیست و قسمت های اصلی آن چیست، بیایید ببینیم چگونه می توانیم یک API در پایتون ایجاد کنیم.

نحوه ایجاد API در پایتون

راه های مختلفی برای ایجاد یک API در پایتون وجود دارد که پرکاربردترین آنها FastAPI و Flask هستند. بنابراین، من نحوه کار هر دو را توضیح خواهم داد تا بتوانید از روشی که بیشتر دوست دارید استفاده کنید. بیایید با FastAPI شروع کنیم.

نحوه ایجاد یک API در پایتون با FastAPI

پیش نیاز های استفاده از FastAPI

FastAPI راهی برای ایجاد API در پایتون است که در پایان سال 2018 منتشر شد. بسیار سریع است، اگرچه فقط با Python 3.6+ قابل استفاده است.

برای استفاده از آن، باید این دو کتابخانه را نصب کنید: fastapiو uvicorn .

pip install fastapi
pip install uvicorn

اولین API پایتون شما با FastAPI

اکنون که بسته ها را نصب کرده ایم، به سادگی باید یک فایل در پایتون ایجاد کنیم که در آن API خود را تعریف کنیم. در این فایل، ما باید یک برنامه ایجاد کنیم، که در آن API ها را با نقاط پایانی، پارامترها و غیره قرار دهیم.

اینجاست که اطلاعات مورد نیاز API را تعریف می کنیم: نقطه پایانی، متد دریافت، آرگومان های ورودی و آنچه API پشت آن انجام خواهد داد.

from fastapi import FastAPI
app = FastAPI()‎

@app.get("/my-first-api")
def hello()‎:
  return {"Hello world!"}

با این کار، یک API بسیار ساده ایجاد شده است که عبارت “Hello world!” را برمی گرداند. همانطور که دیدید، در چند خط تعریف کردیم: متد (get)، نقطه پایانی (“my-first-api/”) و تابعی که این API باید اجرا کند.

حتی می‌توانیم آرگومان‌هایی را به API خود منتقل کنیم تا در عملکرد خود از آن استفاده کند. نوع داده آرگومان نیز باید مشخص باشد.

نکته مهم : FastAPI بررسی می‌کند که نوع داده‌ای که ارسال شده است همان چیزی است که ما تعیین کرده ایم یا نه. و اگر داده ای با نوع متفاوت ارسال شود، fastApi آن را رد می کند. این چیزی است که در سایر فریمورک های ایجاد API (مانند Flask) دیده نمی شود.

بیایید با هم یک مثال از این مورد را بررسی کنیم:

from fastapi import FastAPI
app =from fastapi import FastAPI
app = FastAPI()‎

@app.get("/my-first-api")
def hello(name: str):
  return {'Hello ' + name + '!'} 

حالا وقتی درخواستی را به این API می‌دهیم، باید پارامتر name را به آن ارسال کنیم تا کار کند. یعنی اگر قبلاً درخواست به http://127.0.0.1:8000/my-first-api کافی بود، حالا باید پارامتر name را نیز حتماً ارسال کنیم. بنابراین درخواست به صورت زیر خواهد بود:

 http://127.0.0.1:8000/my-first-api?name=Ander

همانطور که می بینید آرگومان  name را وارد کردیم، این آرگومان الزامی است: اگر در درخواست گنجانده نشود، کار نمی کند. با این حال، ممکن است بخواهیم یک سری آرگومان های اختیاری را نیز اضافه کنیم.

برای این کار، باید مقدار None را به آرگومان خود انتساب دهیم و در این صورت FastAPI آن را به درستی تفسیر خواهد کرد.

مثال: یک API ایجاد می کنیم که می توانید به صورت اختیاری متغیر  name را به آن ارسال کنید. اگر متغیر name ارسال شود، “Hello {name}!” چاپ می شود و اگر نه، “Hello!”

from fastapi import FastAPI

app = FastAPI()‎

@app.get("/my-first-api")
def hello(name = None):

    if name is None:
        text = 'Hello!'

    else:
        text = 'Hello ' + name + '!'

    return text

در این صورت، اگر درخواست http://127.0.0.1:8000/my-first-api را به API ارسال کنیم، به درستی اجرا می‌شود و «Hello!» را برمی‌گرداند، در حالی که اگر پارامتر name را اضافه کنیم، مثلاً، http://127.0.0.1:8000/my-first-api?name=Ander  از آن استفاده می‌کند و عبارت  Hello Ander! برگردانده می شود.

انواع داده های مختلف را با FastAPI برگردانید

در اکثر موارد، API معمولاً یک متن را برمی‌گرداند، اگرچه بسیاری اوقات می‌تواند انواع دیگری از داده‌ها، مانند DataFrame یا یک تصویر را نیز برگرداند.

وقتی اشیاء “عادی” مانند DataFrame را برگردانیم، ماژول FastAPI آن را مستقیماً به یک فایل JSON تبدیل می کند. مثال:

from fastapi import FastAPI

app = FastAPI()‎

@app.get("/get-iris")
def get_iris()‎:

    import pandas as pd
    url ='https://gist.githubusercontent.com/curran/a08a1080b88344b0c8a7/raw/0e7a9b0a5d22642a06d3d5b9bcbad9890c8ee534/iris.csv'
    iris = pd.read_csv(url)

    return iris

اگر به نقطه پایانی /get-iris درخواست بدهیم، پاسخ زیر را دریافت خواهیم کرد:

resp.text
'{"sepal_length":{"0":5.1,"1":4.9,"2":4.7,"3":4.6,"4":5.0,"5":5.4,"6":4.6,"7":5.0,"8":4.4,"9":4.9,"10":5.4,"11":4.8,"12":4.8,"13":4.3,"14":5.8,"15":5.7,"16":5.4,"17":5.1,"18":5.7,"19":5.1,"20":5.4,"21":5.1,"22":4.6,"23":5.1,"24":4.8,"25":5.0,"26":5.0,"27":5.2,"28":5.2,"29":4.7,"30":4.8,"31":5.4,"32":5.2,"33":5.5,"34":4.9,"35":5.0,"36":5.5,"37":4.9,"38":4.4,"39":5.1,"40":5.0,"41":4.5,"42":4.4,"43":5.0,"44":5.1,"45":4.8,"46":5.1,"47":4.6,"48":5.3,"49":5.0,"50":7.0,...

همانطور که می بینید Fast API، این Data Frame را مستقیماً به یک شیء JSON تبدیل می کند. اما، تصاویر یا ویدیوها چطور؟

FastAPI بر پایه starlette است، بنابراین برای پاسخگویی با تصاویر یا نمادها، می توانیم از هر دو StreamingResponse و  FileResponse استفاده کنیم. در هر صورت نیاز به نصب aiofiles داریم.

بنابراین، اگر بخواهیم تصویری را در API خود نمایش دهیم، برنامه FastAPI ما به شکل زیر خواهد بود:

@app.get("/plot-iris")
def plot_iris()‎:

    import pandas as pd
    import matplotlib.pyplot as plt

    url ='https://gist.githubusercontent.com/curran/a08a1080b88344b0c8a7/raw/0e7a9b0a5d22642a06d3d5b9bcbad9890c8ee534/iris.csv'
    iris = pd.read_csv(url)

    plt.scatter(iris['sepal_length'], iris['sepal_width'])
    plt.savefig('iris.png')
    file = open('iris.png', mode="rb")

    return StreamingResponse(file, media_type="image/png")

همانطور که می بینیم، ایجاد یک API در پایتون با FastAPI بسیار ساده و بسیار متنوع است. اما چگونه می توانیم بررسی کنیم که API به درستی کار می کند؟

بررسی عملکرد یک API در FastAPI

همانطور که در ابتدای این بخش گفتم، برای ایجاد یک API در FastAPI باید کد خود را در یک فایل پایتون قرار دهیم، ترجیحاً main.py. همچنین، باید uvicorn را نصب کرده باشیم. با در نظر گرفتن این موضوع، می توانیم API خود را به روشی بسیار ساده و با کد زیر اجرا کنیم:

uvicorn main:app --reload

این دستور برنامه ما را اجرا می‌کند و ما می‌توانیم به API خود هم در سطح مرورگر و هم از طریق رایانه خود دسترسی پیدا کنیم. API هنوز در جایی آپلود نشده است، بنابراین از لوکال هاست قابل دسترسی خواهد بود. شما می توانید هم با آدرس http://127.0.0.1/ و هم با  http://localhost/ به آن دسترسی داشته باشید. اگرچه باید این آدرس ها را در همان پورتی که API را اجرا می کند، باز کنید. برای فهمیدن پورت، به نظر من، ساده ترین کار استفاده از لینکی است که uvicorn هنگام اجرای API به شما می دهد. در تصویر زیر می بینید که از پورت 8000 استفاده شده است:

نحوه ایجاد API در پایتون

اکنون یک درخواست به یکی از نقاط پایانی این API که ساختیم ارسال می کنم:

import requests
from PIL import Image
import io

resp = requests.get('http://127.0.0.1:8000/plot-iris')
file = io.BytesIO(resp.content)
im = Image.open(file)
im.show()‎

همانطور که می بینیم، API ما تصویر را به درستی به ما برمی گرداند. بیایید اکنون اولین نقطه پایانی را که ایجاد کرده ایم امتحان کنیم:

resp = requests.get('http://127.0.0.1:8000/my-first-api?name=Ander')
resp.text
'"Hello Ander!"'

علاوه بر این، FastAPI خود مستندات API ما را نیز به صورت swagger ایجاد می کند، که می توانیم از مسیر docs به آنها دسترسی داشته باشیم. در مورد این API، همین که API فعال شد، می توانم از طریق آدرس  http://127.0.0.1:8000/docs به آن دسترسی داشته باشم. همانطور که در تصویر زیر مشاهده می شود:

نحوه ایجاد API در پایتون

علاوه بر این، روش دیگری نیز برای مستندسازی API وجود دارد. با OpenAPI، که از طریق نقطه پایانی /redoc قابل دسترس است، همانطور که در زیر می بینیم:

نحوه ایجاد API در پایتون

همانطور که می بینید، ایجاد یک API با FastAPI بسیار ساده، بسیار سریع و شهودی است. با این حال، FastAPI تنها راه ایجاد یک API در پایتون نیست. راه دیگر برای انجام آن استفاده از flask است.

نحوه ایجاد یک API در پایتون با Flask

نحوه ایجاد یک API با Flask

اول از همه، برای ایجاد یک API در پایتون با استفاده از Flask باید بسته‌های flask و  flask-restful را نصب کنیم. هنگامی که کتابخانه ها را نصب کردیم، باید سرور خود را ایجاد کنیم، همانطور که با FastAPI انجام دادیم. با دستور زیر می توانیم این کار را انجام دهیم:

from flask import Flask

app = Flask()‎  

علاوه بر این، ما باید نشان دهیم که سرور به همراه پورتی که باید راه اندازی شود، راه اندازی می شود. برای انجام این کار، در انتهای برنامه ما باید کد زیر را وارد کنیم:

if __name__ == '__main__':
    app.run(debug=True, port=8000)

هنگامی که سرور خود را ایجاد کردیم و مشخص کردیم که در کدام پورت باید اجرا شود، می توانیم شروع به ایجاد API های خود کنیم. برای ایجاد یک API در پایتون با Flask، باید نشان دهیم: نقطه پایانی، روش و تابعی که باید در آن نقطه پایانی اجرا شود. بیایید مثالی با یک API ببینیم که به سادگی متن “Hello world!” را برمی گرداند.

from flask import Flask, jsonify, request,send_file

app = Flask()‎

@app.route('/my-first-api', method = ['GET'])

def hello()‎:

    return "Hello world!"

همانطور که می بینید، در این مورد، زمانی که مسیر سرور را با آن تعریف می کنیم، هم نقطه پایانی و هم متد را تعریف می کنیم. @app.route.در مورد من، من متد GET را تعریف کرده ام، اگرچه لازم نیست، زیرا به طور پیش فرض، Flask از روش GET بنابراین تعریف متد فقط در صورتی الزامی است که بخواهیم از روشی غیر از GET استفاده کنیم، یعنی از POST، PUT یا DELETE استفاده کنیم.

نحوه ارسال پارامترها به API در Flask

بسیاری از اوقات، API های ما به پارامترهایی نیاز دارند. یک مثال واضح زمانی است که ما یک مدل را تولید می کنیم: هر ورودی مدل باید یک پارامتر از API ما باشد.

از این نظر، می‌توانیم هنگام درخواست، آرگومان‌هایی را به API خود در Flask ارسال کنیم. در این صورت، برای اینکه بتوانیم از آنها در تابع استفاده کنیم، ابتدا باید آنها را از درخواست استخراج کنیم، که این کار را با request.args.get انجام می دهیم. بله، این تا حدودی با نحوه انجام آن در FastAPI متفاوت است و به نظر من در Flask دست و پا گیرتر از FastApi است.

برای مثال، بیایید ببینیم که چگونه یک API ایجاد کنیم که یک پارامتر نام را دریافت کند و از “Hello {name}!” چاپ کند.

@app.route('/my-first-api', methods = ['GET'])
def hello()‎:

    name = request.args.get('name')

    if name is None:
        text = 'Hello!'

    else:
        text = 'Hello ' + name + '!'

    return text

در این مورد، API ما ، پارامتر name را با دو گزینه از URL درخواست می گیرد:

  1. اگر پارامتر name پاس نشده باشد، به عنوان مثال: http://127.0.0.1:8000/my-first-apiپارامتر name None خواهد بود، بنابراین API Hello! را برمی گرداند .
  2. اگر nameپارامتر ارسال شده باشد، به عنوان مثال http://127.0.0.1:8000/my-first-api?name=Ander، این API از این پارامتر برای ایجاد پاسخ استفاده می‌کند که در این صورت پاسخ برابر است با Hello Ander! .

مهم : Flask پارامترهای درخواست را ارزیابی نمی کند، بنابراین باید خودمان ارزیابی انجام دهیم، در غیر این صورت در تابع استفاده می شود. برای مثال، اگر آدرس  http://127.0.0.1:8000/my-first-api?name=2 را درخواست کنیم API مقدار Hello 2!  را برمی گرداند، زیرا تأیید نکرده است که مقدار پارامتر باید یک رشته باشد و نه یک عدد یا هر نوع شی دیگری.

انواع داده های مختلف را با Flask برگردانید

همانطور که می بینیم، تا کنون رشته های متنی را برگردانده ایم. با این حال، API ها معمولا داده ها را با فرمت JSON برمی گرداند. برای این کار باید از jsonifyماژول استفاده کنیم. بیایید نمونه ای از نحوه برگرداندن رشته قبلی را ببینیم، اما این بار با فرمت JSON:

@app.route('/my-first-api', methods = ['GET'])
def hello()‎:

    name = request.args.get('name')

    if name is None:
        text = 'Hello!'

    else:
        text = 'Hello ' + name + '!'

    return jsonify({"message": text})

به همین ترتیب، می‌توانیم نوع دیگری از شی، مانند مجموعه داده را برگردانیم. بیایید ببینیم که یک مثال چگونه خواهد بود و یک نقطه پایانی جدید ایجاد می کند که مجموعه داده عنبیه را از طریق یک درخواست GET برمی گرداند:

@app.route("/get-iris")
def get_iris()‎:

    import pandas as pd
    url ='https://gist.githubusercontent.com/curran/a08a1080b88344b0c8a7/raw/0e7a9b0a5d22642a06d3d5b9bcbad9890c8ee534/iris.csv'
    iris = pd.read_csv(url)

    return jsonify({
        "message": "Iris Dataset",
        "data": iris.to_dict()‎
        })

برای ارسال یک DataFrame، ابتدا باید آن را به یک شی تبدیل کنیم که می تواند به JSON تبدیل شود، مانند یک دیکشنری. با این کار پاسخی مانند زیر خواهیم داشت:

resp.json()‎
{'data': {'petal_length': {'0': 1.4, '1': 1.4, '2': 1.3, '3': 1.5, '4': 1.4, '5': 1.7, '6': 1.4, '7': 1.5, '8': 1.4, '9': 1.5, '10': 1.5, '11': 1.6, '12': 1.4, '13': 1.1, '14': 1.2, '15': 1.5, '16': 1.3, '17': 1.4, '18': 1.7, '19': 1.5, '20': 1.7, '21': 1.5, '22': 1.0, '23': 1.7, '24': 1.9, '25': 1.6, '26': 1.6, '27': 1.5, '28': 1.4, '29': 1.6, '30': 1.6, '31': 1.5, '32': 1.5, '33': 1.4, '34': 1.5, '35': 1.2, '36': 1.3, '37': 1.5, '38': 1.3, '39': 1.5, '40': 1.3, '41': 1.3, '42': 1.3, '43': 1.6, '44': 1.9, '45': 1.4, '46': 1.6, '47': 1.4, '48': 1.5, '49': 1.4, '50': 4.7, ...

در نهایت، آیا می توانید تصاویر را از طریق یک API در Python ساخته شده در Flask ارسال کنید؟ در FastAPI دیدیم که می‌تواند و البته فلاسک هم کمتر نمی‌شد. در واقع، روش انجام آن بسیار شبیه است، فقط در این مورد، ما باید محتوا را در خود فلاسک (یا هر دایرکتوری دیگری که هست) ذخیره کنیم و با استفاده از send_fileتابع ارسال کنیم.

@app.route("/plot-iris")
def plot_iris()‎:

    import pandas as pd
    import matplotlib.pyplot as plt
    import os

    url ='https://gist.githubusercontent.com/curran/a08a1080b88344b0c8a7/raw/0e7a9b0a5d22642a06d3d5b9bcbad9890c8ee534/iris.csv'
    iris = pd.read_csv(url)

    plt.scatter(iris['sepal_length'], iris['sepal_width'])
    plt.savefig('flask/iris.png')

    return send_file('iris.png')

اکنون که می دانیم چگونه انواع مختلف محتوا را با یک API Python ایجاد شده با Flask ارسال کنیم، بیایید ببینیم چگونه بررسی کنیم که API ما درست کار می کند.

عملکرد Flask API را بررسی کنید

قبل از اجرای یک API Python ساخته شده در Flask، باید بررسی کنیم که آیا آن را در یک پورت در معرض نمایش قرار می دهیم. برای این کار باید کدی را که ذکر کردم و در زیر قرار دادم وارد کنیم:

if __name__ == '__main__':
    app.run(debug=True, port=8000)

بنابراین، برای اجرای برنامه ما فقط باید فایل پایتون خود را در جایی که API ایجاد کرده ایم اجرا کنیم. در مورد من دستور زیر است:

python flask/main.py

با این کار کدی مانند شکل زیر تولید می شود:

نحوه ایجاد API در پایتون

همانطور که می بینید، API ما در هاست محلی ما، در پورتی که ما نشان داده ایم (در مورد من، پورت 8000) اجرا می شود.

بنابراین، برای آزمایش API، می‌توانیم به سادگی به مرورگر خود برویم و به نقاط پایانی برویم یا مستقیماً درخواست‌هایی را از پایتون انجام دهیم:

resp.json()‎
{'message': 'Hello Ander!'}

همانطور که می بینیم، API محتوا را به درستی برمی گرداند.

همچنین می‌توانیم اسناد Swagger و OpenApi را به API خود در Flask اضافه کنیم، اگرچه انجام این کار کمی خسته‌کننده‌تر از FastAPI است.

نتیجه

همانطور که می بینید، ایجاد API با استفاده از هر دوی FastApi و Flask بسیار ساده است، اگرچه آنها تفاوت های خاصی دارند:

  • Flask چارچوبی است که به شما امکان می دهد کل برنامه های وب را ایجاد کنید.
  • FastAPI اعتبارسنجی انواع داده‌هایی را که انجام می‌دهیم، و همچنین کل فرآیند مستندسازی را انجام می‌دهد، در مقایسه با اینکه آیا آن را در Flask انجام می‌دهیم، در زمان ما صرفه‌جویی می‌کند.

بنابراین، توصیه من این است که اگر فقط می‌خواهید API ایجاد کنید، آن را در FastAPI انجام دهید، زیرا مطمئناً سریع‌تر خواهد بود. با این حال، اگر می خواهید یک رابط کاربری کامل (front و back) ایجاد کنید و API بخشی از اکوسیستم است، توصیه می کنم از Flask استفاده کنید، زیرا همه چیز تحت یک چارچوب خواهد بود و برای شما بسیار آسان تر خواهد بود.

در هر صورت، ایجاد API در پایتون برای هر شخص اختصاص داده شده در دنیای داده بسیار ساده و اساسی است. چه برای اجرای فرآیندها و چه برای تولید الگوریتم های یادگیری ماشین، مطمئنا API ها بخشی از این فرآیند هستند.

zohreh

مدیر وب سایت بکندباز

دیدگاه‌ها

*
*