Python Graphene
Python被认为是最受欢迎的通用编程语言之一,因为它易于使用和简单。除此之外,GraphQL是一种声明性的查询语言,用于应用程序编程接口和服务器运行时,与Python非常搭配。然而,目前提供给程序员的关于如何在Python中使用GraphQL的逐步教程非常少。
Graphene是在像Python这样的编程语言中创建GraphQL端点的最佳库之一。它具有动态进化的特点。它包含了适用于Django、SQLAlchemy和MongoDB的相当完整的ORM帮助库。实现一些简单的功能非常容易。Graphene的文档还有很大的提升空间。通过它的文档,使用GraphQL实现一些简单的功能是非常容易的;然而,要实现一些复杂、生产就绪和强大的功能则是另一回事。
在接下来的教程中,我们将重点介绍如何使用Graphene库在Python中使用GraphQL。
但在进入正题之前,让我们简要讨论一下教程的目标和要求。
目标
我们将构建一个基于爬取服务的项目。我们将使用抓取库来完成这个项目。
这个爬取服务将以以下方式提交客户端请求:
{
website(url: "https://www.javatpoint.com/python-tutorial") {
title
image
}
}
服务器的响应将会是:
{
"data": {
"website": {
"title": "Learn Python Tutorial - javatpoint",
"image": "https://static.javatpoint.com/images/logo/jtp_logo",
}
}
}
每个网站还将涉及一个描述字段。
设置环境
假设我们已经有本地可用的Python 3版本,让我们首先为依赖项创建一个虚拟环境。为了创建一个虚拟环境,让我们先安装virtualenv,如下所示:
语法:
$ pip install virtualenv
$ virtualenv env
输出:
created virtual environment CPython3.9.0.final.0-64 in 45108ms
creator CPython3Windows(dest=D:\Python\env, clear=False, no_vcs_ignore=False, global=False)
seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=C:\Users\Mango\AppData\Local\pypa\virtualenv)
added seed packages: pip==21.2.2, setuptools==57.4.0, wheel==0.36.2
activators BashActivator,BatchActivator,FishActivator,PowerShellActivator,PythonActivator
让我们激活虚拟环境。
Windows、macOS和Linux的语法非常不同。
1.对于Windows:
语法:
$ env\Scripts\activate
2.对于 MacOS / Linux:
语法:
$ source env/bin/activate
现在,我们来了解一下项目所需的库。
- Extraction
- Graphene
- Flask-graphql
- Requests
我们可以使用pip安装它们,如下所示。
语法:
$ pip install extraction
$ pip install graphene
$ pip install flask-graphql
$ pip install requests
或者
我们可以按照下面所示的方式将它们作为一组安装:
语法:
$ pip install extraction graphene flask-graphql requests
抓取和提取数据
在我们开始学习GraphQL之前,让我们简要了解一下从网站中抓取和提取数据的代码片段。
示例:
# importing the required libraries
import graphene
import extraction
import requests
# defining the function for extraction
def extract(myurl):
myhtml = requests.get(myurl).text
extrctd = extraction.Extractor().extract(myhtml, source_url = myurl)
print(extrctd)
# calling the function
extract('https://www.javatpoint.com/python-tutorial')
输出:
解释:
在上面的代码片段中,我们导入了所需的库并定义了一个名为 extract() 的提取函数。
在函数内部,我们使用requests模块请求URL的详细信息,并将这些详情存储在名为 myhtml 的变量中。然后,我们使用提取模块的 Extractor()
函数来提取用户所需的数据,并将其打印给用户。
最后,我们调用 extract() 函数,指定我们要从中提取数据的URL。
我们可以观察到,每个提取的对象生成可用的不同数据部分,如 title、url、image、description 和 feed。
结构
GraphQL结构位于每个GraphQL API的基础上。它有助于描述暴露的API的类型、字段和对象。我们使用Graphene库将模式描述为Python中的对象。
我们可以以非常简单的方式编写描述提取的网站的模式,如下所示:
示例:
# importing the graphene library
import graphene
# defining a class
class my_Website(graphene.ObjectType):
my_url = graphene.String(required = True)
my_title = graphene.String()
my_description = graphene.String()
my_image = graphene.String()
解释:
在上面的代码片段中,我们导入了graphene库并定义了一个类, myWebsite 该类继承了graphene库的 ObjectType 类。这个 ObjectType 作为一个构建块,用于定义模式中字段与检索其数据的方式之间的关系。在类内部,我们定义了不同的字段,并使用graphene库的 String() 描述字段的类型; 多个字段可能是我们描述的其他对象或者其他 链表,标量,枚举, 等等。
非常意外的是,我们还需要编写一个描述查询的模式,以便检索这些对象:
示例:
# importing the graphene library
import graphene
# defining the class
class my_Query(graphene.ObjectType):
website1 = graphene.Field(my_Website, my_url = graphene.String())
# defining the function
def resolv_website(self, info, my_url):
extrctd = extract(my_url)
return my_Website(my_url = my_url,
my_title = extrctd.title,
my_description = extrctd.description,
my_image = extrctd.image,
)
解释:
在上面的代码片段中, website1 是我们支持查询的对象类型, my_url 是我们将传递给解析函数的参数,然后 website1 对象通过每个请求调用 resolv_website 函数。
最后一步是创建 graphene.Schema 的一个实例,我们将在服务器中传递该实例,以描述我们创建的新API。让我们考虑以下相同的代码片段。
示例:
my_schema = graphene.Schema(query = my_Query)
完成这些操作后,我们成功地为项目创建了模式。
以下是完整的代码:
文件:my_schema.py
# importing the required libraries
import graphene
import extraction
import requests
# defining the function for extraction
def extract(my_url):
myhtml = requests.get(my_url).text
extrctd = extraction.Extractor().extract(myhtml, source_url = my_url)
print(extrctd)
return extrctd
# defining the class
class my_Website(graphene.ObjectType):
my_url = graphene.String(required = True)
my_title = graphene.String()
my_description = graphene.String()
my_image = graphene.String()
# defining the class
class my_Query(graphene.ObjectType):
website1 = graphene.Field(my_Website, my_url = graphene.String())
# defining the function
def resolv_website(self, info, my_url):
extrctd = extract(my_url)
return my_Website(my_url = my_url,
my_title = extrctd.title,
my_description = extrctd.description,
my_image = extrctd.image,
)
my_schema = graphene.Schema(query = my_Query)
服务器
现在我们已经编写了模式,我们可以使用 flask
和 flask-graphql
的帮助来通过HTTP提供服务。
让我们考虑以下代码片段来创建一个服务器。
**文件:my_server.py**
# importing the required library
from flask import Flask
from flask_graphql import GraphQLView
import my_schema
# using the Flask() function to create app
my_app = Flask(__name__)
# setting URL rules
my_app.add_url_rule(
'/',
view_func = GraphQLView.as_view('graphql', schema = my_schema, graphiql = True)
)
my_app.run()
说明:
在上面的代码片段中,我们导入了所需的库,并导入了之前创建的名为 my_schema 的文件。然后,我们使用 Flask() 函数,并指定参数为 __name__ 来创建应用程序。我们还使用 add_url_rule() 函数来添加不同的URL规则,其中我们指定了不同的参数,并在最后使用 run() 函数来执行应用程序。
现在,我们可以使用以下语法运行服务器:
语法:
$ python my_server.py
一旦我们输入了上述语法,服务器将开始运行在 localhost:5000 或者 http://127.0.0.1:5000/.
相同操作的输出如下所示:
输出:
Serving Flask app "my_server" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
客户端
尽管存在这些,但我们不需要特殊的GraphQL客户端来执行对新API的API请求; 我们可以继续使用我们习惯于的HTTP客户端,我们在以下示例中使用请求。
文件: my_client.py
# importing the requests library
import requests
# defining the query
my_query = """
{
website(url: "https://www.javatpoint.com/python-tutorial") {
title
image
description
}
}
"""
# defining the response
my_response = requests.post("http://127.0.0.1:5000/", params = {'query': my_query})
print(my_response.text)
输出:
{
"data": {
"website": {
"title": "Learn Python Tutorial - javatpoint",
"image": "https://static.javatpoint.com/images/logo/jtp_logo",
"description": "Learn Python Tutorial for beginners and profession"
}
}
}
解释:
在上面的代码片段中,我们导入了 requests 库,并定义了一个查询 my_query ,该查询将发送到服务器。然后,我们定义了一个变量 my_response, 它将以响应的形式存储从服务器返回的数据。最后,我们打印出响应给用户。
用户还可以自定义 my_query 变量的内容,以检索不同的字段,甚至可以使用别名一次检索多个对象。
自省
在GraphQL中最强大的方面之一是它的服务器支持自省。自省允许人类和自动化工具理解可用的对象和操作。
一个很好的示例是,当我们运行我们构建的示例时,我们可以导航到 http://127.0.0.1:5000 并直接使用GraphiQL测试新的API。
这些能力不仅限于GraphiQL,我们还可以借助相同的查询接口进行集成,以查询新的API。让我们考虑一个简单的示例,我们询问示例服务暴露的可用查询:
{
__type(name: "Query") {
fields {
name
args {
name
}
}
}
}
服务器回答会是:
{
"data": {
"__type": {
"fields": [
{
"name": "website",
"args": [{ "name": "url" }]
}
]
}
}
}
有很多基于内省的其他查询可用,编写起来非常笨拙;然而,它们为工具构建者提供了巨大的力量。