如何在Python从 Jira 获取数据?
Jira 是一种敏捷的项目管理工具,由 Atlassian 开发,主要用于跟踪项目错误和问题。它逐渐发展成为一个强大的工作管理工具,可以处理敏捷方法的所有阶段。在本文中,我们将学习如何使用Python从 Jira 获取数据。
获取数据有两种方式:
- 将 JIRA 库用于Python。
- 使用 JIRA Rest API。
Jira软件工具中所需的配置如下:
- 创建一个 Jira 用户帐户。
- 创建一个域名,添加一个项目,并记录一些问题或错误。我们的任务是使用Python代码获取、发布数据。
- 我们需要一个有效的令牌来进行身份验证,可以从链接 https://id.atlassian.com/manage/api-tokens 获取。
JQL: JQL 代表 Jira 查询语言。这是一种获取 JIRA 相关数据的有效方式。它可以在 JIRA 库和 API 方法中用于获取数据。这涉及形成查询、过滤信息、关于相关错误、项目、问题等。可以在查询中使用不同运算符和关键字的组合。
使用Python 的Jira 库获取数据
JIRA,是一个Python库,用于与 JIRA 工具连接。与 API 方法相比,该库易于使用,用于获取与问题、项目、工作日志等相关的数据。该库需要大于 3.5 的Python版本。
使用以下命令安装 jira:
pip install jira
方法:
- 导入 jira 模块。
- 使用以下命令构建 Jira 客户端实例:
- 服务器密钥,即您的域名,是在 Atlassian 帐户上创建的。
- 基本身份验证参数、您注册的电子邮件 ID 以及收到的唯一令牌。
- 获取绕过身份验证参数的 JIRA 客户端实例。
- 根据项目名称搜索所有提到的问题(使用打印语句显示详细信息,如问题键、摘要、报告者姓名。)。
下面是实现:
Python
# import the installed Jira library
from jira import JIRA
# Specify a server key. It should be your
# domain name link. yourdomainname.atlassian.net
jiraOptions = {'server': "https://txxxxxxpython.atlassian.net"}
# Get a JIRA client instance, pass,
# Authentication parameters
# and the Server name.
# emailID = your emailID
# token = token you receive after registration
jira = JIRA(options=jiraOptions, basic_auth=(
"prxxxxxxh@gmail.com", "bj9xxxxxxxxxxxxxxxxxxx5A"))
# Search all issues mentioned against a project name.
for singleIssue in jira.search_issues(jql_str='project = MedicineAppBugs'):
print('{}: {}:{}'.format(singleIssue.key, singleIssue.fields.summary,
singleIssue.fields.reporter.displayName))
Python
# import the installed Jira library
from jira import JIRA
# Specify a server key. It is your domain
# name link.
jiraOptions = {'server': "https://txxxxxxpython.atlassian.net"}
# Get a JIRA client instance, Pass
# Authentication parameters
# and Server name.
# emailID = your emailID
# token = token you receive after registration
jira = JIRA(options = jiraOptions,
basic_auth = ("prxxxxxxh@gmail.com",
"bj9xxxxxxxxxxxxxxxxxxx5A"))
# While fetching details of a single issue,
# pass its UniqueID or Key.
singleIssue = jira.issue('MED-1')
print('{}: {}:{}'.format(singleIssue.key,
singleIssue.fields.summary,
singleIssue.fields.reporter.displayName))
Python
# Import the required libraries
import requests
from requests.auth import HTTPBasicAuth
import json
import pandas as pd
# URL to Search all issues.
url = "https://txxxxxxpython.atlassian.net/rest/api/2/search"
# Create an authentication object,using
# registered emailID, and, token received.
auth = HTTPBasicAuth("prxxxxxxh@gmail.com",
"bj9xxxxxxxxxxxxxxxxxxx5A")
# The Header parameter, should mention, the
# desired format of data.
headers = {
"Accept": "application/json"
}
# Mention the JQL query.
# Here, all issues, of a project, are
# fetched,as,no criteria is mentioned.
query = {
'jql': 'project =MedicineAppBugs '
}
# Create a request object with above parameters.
response = requests.request(
"GET",
url,
headers=headers,
auth=auth,
params=query
)
# Get all project issues,by using the
# json loads method.
projectIssues = json.dumps(json.loads(response.text),
sort_keys=True,
indent=4,
separators=(",", ": "))
# The JSON response received, using
# the requests object,
# is an intricate nested object.
# Convert the output to a dictionary object.
dictProjectIssues = json.loads(projectIssues)
# We will append,all issues,in a list object.
listAllIssues = []
# The Issue details, we are interested in,
# are "Key" , "Summary" and "Reporter Name"
keyIssue, keySummary, keyReporter = "", "", ""
def iterateDictIssues(oIssues, listInner):
# Now,the details for each Issue, maybe
# directly accessible, or present further,
# in nested dictionary objects.
for key, values in oIssues.items():
# If key is 'fields', get its value,
# to fetch the 'summary' of issue.
if(key == "fields"):
# Since type of object is Json str,
# convert to dictionary object.
fieldsDict = dict(values)
# The 'summary' field, we want, is
# present in, further,nested dictionary
# object. Hence,recursive call to
# function 'iterateDictIssues'.
iterateDictIssues(fieldsDict, listInner)
# If key is 'reporter',get its value,
# to fetch the 'reporter name' of issue.
elif (key == "reporter"):
# Since type of object is Json str
# convert to dictionary object.
reporterDict = dict(values)
# The 'displayName', we want,is present
# in,further, nested dictionary object.
# Hence,recursive call to function 'iterateDictIssues'.
iterateDictIssues(reporterDict, listInner)
# Issue keyID 'key' is directly accessible.
# Get the value of key "key" and append
# to temporary list object.
elif(key == 'key'):
keyIssue = values
listInner.append(keyIssue)
# Get the value of key "summary",and,
# append to temporary list object, once matched.
elif(key == 'summary'):
keySummary = values
listInner.append(keySummary)
# Get the value of key "displayName",and,
# append to temporary list object,once matched.
elif(key == "displayName"):
keyReporter = values
listInner.append(keyReporter)
# Iterate through the API output and look
# for key 'issues'.
for key, value in dictProjectIssues.items():
# Issues fetched, are present as list elements,
# against the key "issues".
if(key == "issues"):
# Get the total number of issues present
# for our project.
totalIssues = len(value)
# Iterate through each issue,and,
# extract needed details-Key, Summary,
# Reporter Name.
for eachIssue in range(totalIssues):
listInner = []
# Issues related data,is nested
# dictionary object.
iterateDictIssues(value[eachIssue], listInner)
# We append, the temporary list fields,
# to a final list.
listAllIssues.append(listInner)
# Prepare a dataframe object,with the final
# list of values fetched.
dfIssues = pd.DataFrame(listAllIssues, columns=["Reporter",
"Summary",
"Key"])
# Reframing the columns to get proper
# sequence in output.
columnTiles = ["Key", "Summary", "Reporter"]
dfIssues = dfIssues.reindex(columns=columnTiles)
print(dfIssues)
输出:
使用 Jira 库,我们还可以获取单个问题的详细信息。
密钥是问题的唯一 ID,我们需要其详细信息。添加Issue后获取,对于一个项目,在平台上,在获取单个问题的详细信息时,传递其UniqueID或Key。
Python
# import the installed Jira library
from jira import JIRA
# Specify a server key. It is your domain
# name link.
jiraOptions = {'server': "https://txxxxxxpython.atlassian.net"}
# Get a JIRA client instance, Pass
# Authentication parameters
# and Server name.
# emailID = your emailID
# token = token you receive after registration
jira = JIRA(options = jiraOptions,
basic_auth = ("prxxxxxxh@gmail.com",
"bj9xxxxxxxxxxxxxxxxxxx5A"))
# While fetching details of a single issue,
# pass its UniqueID or Key.
singleIssue = jira.issue('MED-1')
print('{}: {}:{}'.format(singleIssue.key,
singleIssue.fields.summary,
singleIssue.fields.reporter.displayName))
输出:
使用 Jira Rest API 获取数据
JIRA 服务器平台为问题和工作流提供 REST API。它允许我们在问题、组、仪表板等上执行 CRUD 操作。 Jira Rest API 的开发人员平台有充分的文档记录,可以在 https://developer.atlassian.com/cloud/ 上参考jira/platform/rest/v2/intro/.根据我们的要求,我们需要在平台上查找特定的 URI。在下面的代码片段中,我们正在获取所有问题,提出,反对我们提到的项目“MedicineAppBugs”。
需要的Python库:
- 库 JSON 在Python分发包中可用。
- 使用命令安装请求- pip install requests。
- 使用命令安装熊猫- pip install pandas。
获取 API 链接
- 访问开发者 API。
- 您可以在左侧面板上找到可供开发人员使用的各种 API 选项。例如,除了问题之外,还有用于在“用户”、“项目”上执行 CRUD 操作的 API。
- 在本文中,我们将获取所有问题,因此,我们将选择“问题搜索”选项。我们将选择子选项“使用 JQL(GET) 搜索问题”方法。
- 选择此选项时,将显示 URI “GET /rest/api/2/search”,以及允许的请求参数格式。
- 附加上面的链接,您的域名为 – “https://your-domain.atlassian.net/rest/api/2/search”。这个最终 URL 将有助于获取针对我们项目的所有问题。
方法:
- 导入所需的模块。
- 准备网址,搜索,所有问题。
- 使用注册的 emailID 和收到的令牌创建身份验证对象。
- 传递项目名称,in,JQL 查询。如果您省略 JQL 查询,则将获得针对您的域中所有项目的问题。
- 创建并发送请求对象,使用身份验证、标头对象和 JQL 查询。
- 使用 JSON 加载方法将 JSON 响应转换为Python字典对象。
- 所有问题都作为列表元素出现在主 API 输出中的关键“问题”中。因此,循环遍历每个元素。
- 因为,单个问题单独是一个进一步的嵌套字典对象,使用“iterateDictIssues”函数来获取所需的键。
- 最后,将输出列表附加到 Pandas 的数据框中,并显示它。
注意:请仔细研究 API 输出,以检查您需要的字段的位置和类型。它们可以是嵌套字典或列表对象,并且需要决定相应的函数逻辑。
下面是实现:
Python
# Import the required libraries
import requests
from requests.auth import HTTPBasicAuth
import json
import pandas as pd
# URL to Search all issues.
url = "https://txxxxxxpython.atlassian.net/rest/api/2/search"
# Create an authentication object,using
# registered emailID, and, token received.
auth = HTTPBasicAuth("prxxxxxxh@gmail.com",
"bj9xxxxxxxxxxxxxxxxxxx5A")
# The Header parameter, should mention, the
# desired format of data.
headers = {
"Accept": "application/json"
}
# Mention the JQL query.
# Here, all issues, of a project, are
# fetched,as,no criteria is mentioned.
query = {
'jql': 'project =MedicineAppBugs '
}
# Create a request object with above parameters.
response = requests.request(
"GET",
url,
headers=headers,
auth=auth,
params=query
)
# Get all project issues,by using the
# json loads method.
projectIssues = json.dumps(json.loads(response.text),
sort_keys=True,
indent=4,
separators=(",", ": "))
# The JSON response received, using
# the requests object,
# is an intricate nested object.
# Convert the output to a dictionary object.
dictProjectIssues = json.loads(projectIssues)
# We will append,all issues,in a list object.
listAllIssues = []
# The Issue details, we are interested in,
# are "Key" , "Summary" and "Reporter Name"
keyIssue, keySummary, keyReporter = "", "", ""
def iterateDictIssues(oIssues, listInner):
# Now,the details for each Issue, maybe
# directly accessible, or present further,
# in nested dictionary objects.
for key, values in oIssues.items():
# If key is 'fields', get its value,
# to fetch the 'summary' of issue.
if(key == "fields"):
# Since type of object is Json str,
# convert to dictionary object.
fieldsDict = dict(values)
# The 'summary' field, we want, is
# present in, further,nested dictionary
# object. Hence,recursive call to
# function 'iterateDictIssues'.
iterateDictIssues(fieldsDict, listInner)
# If key is 'reporter',get its value,
# to fetch the 'reporter name' of issue.
elif (key == "reporter"):
# Since type of object is Json str
# convert to dictionary object.
reporterDict = dict(values)
# The 'displayName', we want,is present
# in,further, nested dictionary object.
# Hence,recursive call to function 'iterateDictIssues'.
iterateDictIssues(reporterDict, listInner)
# Issue keyID 'key' is directly accessible.
# Get the value of key "key" and append
# to temporary list object.
elif(key == 'key'):
keyIssue = values
listInner.append(keyIssue)
# Get the value of key "summary",and,
# append to temporary list object, once matched.
elif(key == 'summary'):
keySummary = values
listInner.append(keySummary)
# Get the value of key "displayName",and,
# append to temporary list object,once matched.
elif(key == "displayName"):
keyReporter = values
listInner.append(keyReporter)
# Iterate through the API output and look
# for key 'issues'.
for key, value in dictProjectIssues.items():
# Issues fetched, are present as list elements,
# against the key "issues".
if(key == "issues"):
# Get the total number of issues present
# for our project.
totalIssues = len(value)
# Iterate through each issue,and,
# extract needed details-Key, Summary,
# Reporter Name.
for eachIssue in range(totalIssues):
listInner = []
# Issues related data,is nested
# dictionary object.
iterateDictIssues(value[eachIssue], listInner)
# We append, the temporary list fields,
# to a final list.
listAllIssues.append(listInner)
# Prepare a dataframe object,with the final
# list of values fetched.
dfIssues = pd.DataFrame(listAllIssues, columns=["Reporter",
"Summary",
"Key"])
# Reframing the columns to get proper
# sequence in output.
columnTiles = ["Key", "Summary", "Reporter"]
dfIssues = dfIssues.reindex(columns=columnTiles)
print(dfIssues)
输出: