📜  如何在Python从 Jira 获取数据?

📅  最后修改于: 2022-05-13 01:55:19.840000             🧑  作者: Mango

如何在Python从 Jira 获取数据?

Jira 是一种敏捷的项目管理工具,由 Atlassian 开发,主要用于跟踪项目错误和问题。它逐渐发展成为一个强大的工作管理工具,可以处理敏捷方法的所有阶段。在本文中,我们将学习如何使用Python从 Jira 获取数据。

获取数据有两种方式:

  1. 将 JIRA 库用于Python。
  2. 使用 JIRA Rest API。

Jira软件工具中所需的配置如下:

  1. 创建一个 Jira 用户帐户。
  2. 创建一个域名,添加一个项目,并记录一些问题或错误。我们的任务是使用Python代码获取、发布数据。
  3. 我们需要一个有效的令牌来进行身份验证,可以从链接 https://id.atlassian.com/manage/api-tokens 获取。

JIRA 工具中记录的问题“MedicineAppBugs”项目

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 库发布数据输出。

使用 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 库的一个问题的详细信息

使用 Jira Rest API 获取数据

JIRA 服务器平台为问题和工作流提供 REST API。它允许我们在问题、组、仪表板等上执行 CRUD 操作。 Jira Rest API 的开发人员平台有充分的文档记录,可以在 https://developer.atlassian.com/cloud/ 上参考jira/platform/rest/v2/intro/.根据我们的要求,我们需要在平台上查找特定的 URI。在下面的代码片段中,我们正在获取所有问题,提出,反对我们提到的项目“MedicineAppBugs”。

需要的Python库:

  1. 库 JSON 在Python分发包中可用。
  2. 使用命令安装请求- pip install requests。
  3. 使用命令安装熊猫- 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)

输出:

在Python代码中使用 JIRA REST API 从 JIRA 工具收到的问题