使用Python实现对接Hadoop集群(通过Hive)并提供API接口

安装必要的库

首先,确保已经安装了以下库:

python 复制代码
pip install flask
pip install pyhive

代码实现

1. app.py(主应用文件)

python 复制代码
from flask import Flask, jsonify, request, abort
from pyhive import hive
import re
from datetime import datetime

app = Flask(__name__)

# Hive连接配置
HIVE_HOST = "hadoop-cluster-ip"
HIVE_PORT = 10000
HIVE_USERNAME = "your_username"
HIVE_PASSWORD = "your_password"

# 日期格式正则表达式,用于校验输入的日期格式
DATE_FORMAT_REGEX = re.compile(r'^\d{4}-\d{2}-\d{2}$')


def validate_date(date_str):
    """
    校验日期字符串是否符合指定格式(YYYY-MM-DD)
    """
    if not DATE_FORMAT_REGEX.match(date_str):
        raise ValueError("日期格式不正确,请使用YYYY-MM-DD格式。")
    try:
        datetime.strptime(date_str, '%Y-%m-%d')
        return True
    except ValueError:
        raise ValueError("日期格式不正确,请使用YYYY-MM-DD格式。")


@app.route('/api/orders', methods=['GET'])
def get_orders():
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')

    # 校验日期参数格式
    try:
        if start_date:
            validate_date(start_date)
        if end_date:
            validate_date(end_date)
    except ValueError as e:
        abort(400, description=str(e))

    try:
        # 连接Hive
        connection = hive.connect(
            host=HIVE_HOST,
            port=HIVE_PORT,
            username=HIVE_USERNAME,
            password=HIVE_PASSWORD
        )

        cursor = connection.cursor()

        # 构建查询语句,添加必要的防止SQL注入的处理
        query = f"SELECT order_id, order_date, order_amount FROM orders WHERE order_date BETWEEN '{start_date}' AND '{end_date}'"
        query = query.replace("'", "''")  # 将单引号替换为两个单引号,防止SQL注入

        cursor.execute(query)
        results = cursor.fetchall()

        # 将结果转换为字典列表形式
        orders = []
        for row in results:
            order = {
                "order_id": row[0],
                "order_date": row[1],
                "order_amount": row[2]
            }
            orders.append(order)

        cursor.close()
        connection.close()

        return jsonify(orders)

    except hive.DatabaseError as e:
        # 针对Hive数据库相关错误进行更详细的错误处理
        abort(500, description=f"Hive数据库错误: {str(e)}")
    except Exception as e:
        abort(500, description=f"其他错误: {str(e)}")


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

代码解析

输入参数校验

复制代码
定义了validate_date函数,通过正则表达式和datetime.strptime来严格校验输入的日期参数是否符合YYYY-MM-DD格式。如果不符合格式,将直接返回400错误给客户端,提示正确的日期格式要求。

错误处理

复制代码
●	在get_orders函数中,对可能出现的不同类型的错误进行了更细致的处理。对于Hive数据库相关的错误(如连接失败、查询失败等),会返回500错误并明确告知是Hive数据库错误及具体错误信息。对于其他一般性的错误,同样返回500错误并给出相应的错误描述。

安全防护(防止SQL注入)

复制代码
●	在构建查询语句时,对输入的日期参数进行了处理,将单引号替换为两个单引号。这样可以在一定程度上防止SQL注入攻击,确保查询语句的安全性。

单元测试

  • 以下是使用Python的unittest模块对代码进行单元测试的示例:
python 复制代码
import unittest
from unittest.mock import patch
from app import app, validate_date

class TestApp(unittest.TestCase):

    def setUp(self):
        self.app = app.test_client()

    def test_validate_date_valid(self):
        self.assertTrue(validate_date('2024-11-10'))

    def test_validate_date_invalid_format(self):
        with self.assertRaises(ValueError) as context:
            validate_date('2024/11/10')
        self.assertEqual(str(context.exception), "日期格式不正确,请使用YYYY-MM-DD格式。")

    def test_validate_date_invalid_value(self):
        with self.assertRaises(ValueError) as context:
            validate_date('2024-13-32')
        self.assertEqual(str(context.exception), "日期格式不正确,请使用YYYY-MM-DD格式。")

    @patch('app.hive.connect')
    def test_get_orders_success(self, mock_connect):
        # 模拟查询结果
        mock_cursor = mock_connect.return_value.cursor.return_value
        mock_cursor.fetchall.return_value = [(1, '2024-11-10', 100.0)]

        response = self.app.get('/api/orders?start_date=2024-11-10&end_date=2024-11-10')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.get_json(), [{"order_id": 1, "order_date": "2024-11-10", "order_amount": 100.0}])

    def test_get_orders_missing_parameters(self):
        response = self.app.get('/api/orders')
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response.get_json()['description'], "日期格式不正确,请使用YYYY-MM-DD格式。")

    @patch('app.hive.connect')
    def test_get_orders_database_error(self, mock_connect):
        mock_connect.side_effect = hive.DatabaseError("模拟数据库错误")

        response = self.app.get('/api/orders?start_date=2024-11-10&end_date=2024-11-10')
        self.assertEqual(response.status_code, 500)
        self.assertEqual(response.get_json()['description'], "Hive数据库错误: 模拟数据库错误")

    @patch('app.hive.connect')
    def test_get_orders_general_error(self, mock_connect):
        mock_connect.side_effect = Exception("模拟一般错误")

        response = self.app.get('/api/orders?start_date=2024-11-10&end_date=2024-11-10')
        self.assertEqual(response.status_code, 500)
        self.assertEqual(response.get_json()['description'], "其他错误: 模拟一般错误")

if __name__ == '__main__':
    unittest.main()

代码块解析

上述单元测试代码主要涵盖了以下几个方面:

测试validate_date函数

• test_validate_date_valid测试了validate_date函数对于有效日期格式的验证是否正确。

• test_validate_date_invalid_format和test_validate_date_invalid_value分别测试了对于无效日期格式和无效日期值的情况,是否能正确抛出ValueError异常并给出正确的错误信息。

测试get_orders函数

• test_get_orders_success通过patch模拟了hive.connect和查询结果,测试了get_orders函数在正常情况下是否能正确返回查询结果和状态码200 。

• test_get_orders_missing_parameters测试了在缺少查询参数时,是否能正确返回400错误及相应的错误描述。

• test_get_orders_database_error和test_get_orders_general_error分别模拟了hive.DatabaseError和一般Exception的情况,测试了get_orders函数在出现不同类型错误时是否能正确返回500错误及相应的错误描述。

通过这些单元测试,可以较为全面地验证优化后的代码的正确性和可靠性,确保各个功能模块能够按照预期工作。

相关推荐
IT研究室几秒前
大数据毕业设计选题推荐-基于大数据的国家药品采集药品数据可视化分析系统-Spark-Hadoop-Bigdata
大数据·hadoop·信息可视化·spark·毕业设计·数据可视化·bigdata
跟橙姐学代码17 分钟前
Python异常处理:告别程序崩溃,让代码更优雅!
前端·python·ipython
蓝纹绿茶37 分钟前
Python程序使用了Ffmpeg,结束程序后,文件夹中仍然生成音频、视频文件
python·ubuntu·ffmpeg·音视频
mahuifa1 小时前
OpenCV 开发 -- 图像基本处理
人工智能·python·opencv·计算机视觉
Lx3521 小时前
Hadoop性能瓶颈分析:从JVM到磁盘IO的全链路优化
大数据·hadoop
大数据点灯人1 小时前
【Flink】Flink Runtime 开发指南
大数据·flink
一个java开发1 小时前
distributed.client.Client 用户可调用函数分析
大数据·python
eqwaak02 小时前
Matplotlib 动态显示详解:技术深度与创新思考
网络·python·网络协议·tcp/ip·语言模型·matplotlib
007php0072 小时前
某大厂MySQL面试之SQL注入触点发现与SQLMap测试
数据库·python·sql·mysql·面试·职场和发展·golang
CodeCraft Studio2 小时前
Excel处理控件Aspose.Cells教程:使用 Python 将 Pandas DataFrame 转换为 Excel
python·json·excel·pandas·csv·aspose·dataframe