……

概述

  • 配置文件
    概念:一种计算机文件,可给 计算机程序 配置 参数和初始设置
    场景:软件开发时,生产环境数据库账号密码 应写到配置文件,不应明文写到代码中
常见的配置文件后缀示例
.properties Kafka的server.properties
用于Java的日志配置文件log4j.properties
.xml Hadoop的core-site.xml
.ini MySQL的my.ini
.cnf MySQL的my.cnf
.conf Redis的redis.conf
.yml ElasticSearch的elasticsearch.yml
.bashrc 每个运行Bash用户的个性化设置
.json.config.js 前端常用

properties文件是Java中的一种配置文件,文件后缀为.properties,内容格式为key=value,用#注释

  • 传参
    本文的传参是指:通过 命令行 来给程序传递参数
    传参方式有:位置传参、键值对传参…
    当参数多于1个时,建议使用 键值对传参
    场景:日期、并行度

规范

  • 为了 数据开发 的 代码规范:
    配置格式 统一使用 properties
    传参方式 统一使用 键值对传参

  • 生产环境的配置文件 统一 存放到HDFS
    测试配置 写到 本地配置文件
    优先级(大者覆盖小者):
    临 时 配 置 > 生 产 配 置 临时配置 > 生产配置 >
    命 令 行 参 数 > H D F S 配 置 文 件 命令行参数 > HDFS配置文件 >HDFS

  • 配置文件命名
    【建议】全小写
    【强制】下划线分隔单词
    示例:sqoop_mysql2hive.properties

  • 配置文件路径(两种方式):
    业务/子业务/存储媒介.properties
    部门/小组/岗位.properties

业务子业务媒介配置文件路径参数
金融 股票 MySQL /config/finance/stock/mysql.properties host
user
password
database
数据中台   HBase /config/data_center/hbase.properties zkUrl
数据中台   Kafka /config/data_center/kafka.properties bootstrap-server
部门小组员工ID配置文件路径参数
IT 大数据 实时计算 /config/it/big_data/rt.properties queue_name
IT 大数据 数据仓库 /config/it/big_data/dw.properties queue_name
IT 算法 自然语言处理 /config/it/ai/nlp.properties queue_name

代码模板

Python2

#!/usr/bin/python2
# coding:utf-8
"""
获取参数的工具类
    获取参数的方式
        1、properties配置文件
        2、命令行传参
    参数格式
        key=value
    命令行传参示例:
        python2 a.py ymd=2021-12-31 sql='带空格的value可用单引号包裹'
    参数优先级(大者覆盖小者)
        命令行参数 > HDFS配置文件 > 本地配置文件
        临时配置 > 生产配置 > 测试配置
详细链接:
    https://yellow520.blog.csdn.net/article/details/122088401
"""


class ParameterUtil:
    def __init__(self, hdfs_file='', local_file=''):
        self.dt = dict()
        if local_file:
            self._read_local_file(local_file)
        if hdfs_file:
            self._cat_hdfs(hdfs_file)
        self._get_cmd_parameters()

    def _read_local_file(self, file_path):
        """从本地读取配置文件,并获取参数"""
        try:
            with open(file_path) as f:
                self._properties2dict(f.read())
        except IOError:
            print('本地配置文件不存在')

    def _cat_hdfs(self, file_path):
        """从HDFS读取配置文件,并获取参数"""
        from subprocess import check_output, CalledProcessError
        cmd = 'hadoop fs -cat ' + file_path
        try:
            self._properties2dict(check_output(cmd, shell=True))
        except CalledProcessError:
            print('HDFS配置文件不存在')

    def _properties2dict(self, properties):
        """properties文件内容解析"""
        for r in properties.strip().split('\n'):
            if (not r.startswith('#')) and (r.find('=') > 0):
                k, v = r.split('=', 1)
                self.dt[k.strip()] = v.strip()

    def _get_cmd_parameters(self):
        """从命令行获取参数"""
        from sys import argv
        for a in argv[1:]:
            k, v = a.split('=', 1)
            self.dt[k.strip()] = v.strip()

    def get(self, key, default=None):
        """获取参数值"""
        return self.dt.get(key, default)

Python3

from time import time, strftime
from datetime import date, timedelta
import os
import platform
from subprocess import check_output, CalledProcessError


class Timer:
    def __init__(self):
        self.t = time()  # 起始秒数

    def __del__(self):
        if self.__str__():
            print('结束时间:%s' % self.now)
            print('运行时间:%s' % self)

    def __str__(self):
        t = self.seconds
        if t < 1:
            return ''
        elif t < 60:
            return '%.2fs' % t
        elif t < 3600:
            return '%.2fmin' % (t / 60)
        else:
            return '%.2fh' % (t / 3600)

    @property
    def seconds(self) -> float:
        """程序运行秒数"""
        return time() - self.t

    @property
    def now(self) -> str:
        """当前时间字符串"""
        return strftime('%Y-%m-%d %H:%M:%S')

    @property
    def today(self) -> date:
        return date.today()

    @property
    def yesterday(self) -> str:
        yesterday = self.today - timedelta(days=1)
        return yesterday.strftime('%Y-%m-%d')

    @property
    def this_year(self) -> int:
        return self.today.year

    @property
    def last_year(self) -> int:
        return self.this_year - 1

    @property
    def this_month(self) -> str:
        """本月,格式YYYY-MM"""
        return '%04d-%02d' % (self.this_year, self.today.month)

    @property
    def last_month(self) -> str:
        """上个月,格式YYYY-MM"""
        last_day_of_last_month = self.today - timedelta(days=self.today.day)  # 上个月的最后一天
        last_month = last_day_of_last_month.month  # 上个月
        year = last_day_of_last_month.year  # 上个月所在的年份
        ym = '%04d-%02d' % (year, last_month)  # 上个月的完整格式:YYYY-MM
        return ym


class Executor(Timer):
    def debug(self, text):
        """仅在Windows打印"""
        if platform.system() == 'Windows':
            print('[DEBUG {}] {}'.format(self.now, text))

    @staticmethod
    def execute(cmd):
        """执行Linux命令"""
        os.system(cmd)

    @staticmethod
    def evaluate(cmd):
        """执行Linux命令并获取返回值"""
        return check_output(cmd, shell=True)


class ParameterUtil(Executor):
    """https://yellow520.blog.csdn.net/article/details/122088401"""

    def __init__(self, *hdfs_files):
        super().__init__()
        self.dt = dict()
        for hdfs_file in hdfs_files:
            self._cat_hdfs(hdfs_file)
        self._get_cmd_parameters()

    def _cat_hdfs(self, file_path):
        """从HDFS读取配置文件,并获取参数"""
        cmd = 'hadoop fs -cat ' + file_path
        try:
            self._properties2dict(self.evaluate(cmd))
        except CalledProcessError:
            print('HDFS配置文件不存在')

    def read_local_file(self, file_path):
        """从本地读取配置文件,并获取参数"""
        try:
            with open(file_path) as f:
                self._properties2dict(f.read())
        except IOError:
            print('本地配置文件不存在')

    def _properties2dict(self, properties):
        """properties文件内容解析"""
        for r in properties.strip().split('\n'):
            if (not r.startswith('#')) and (r.find('=') > 0):
                k, v = r.split('=', 1)
                self.dt[k.strip()] = v.strip()

    def _get_cmd_parameters(self):
        """从命令行获取参数"""
        from sys import argv
        for a in argv[1:]:
            k, v = a.split('=', 1)
            self.dt[k.strip()] = v.strip()

    def get(self, key, default=None):
        """获取参数值"""
        return self.dt.get(key, default)

    @property
    def ymd(self) -> str:
        """获取日期,格式YYYY-MM-DD,默认昨天"""
        return self.get('ymd', self.yesterday)

    @property
    def ym(self) -> str:
        """获取日期,格式YYYY-MM,默认上个月"""
        return self.get('ym', self.last_month)

Java(待完善)

import java.io.FileInputStream;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;

/**
 * ParameterUtil parameters = new ParameterUtil(args, "mysql.properties", "kafka.properties");
 * String ymd = parameters.get("ymd");
 */
public class ParameterUtil {
    Properties p = new Properties();

    public ParameterUtil(String[] args, String... hdfsPaths) {
        //获取HDFS上的配置文件
        for (String hdfsPath : hdfsPaths) {
            catHdfs(hdfsPath);
        }
        //命令行传参
        for (String arg : args) {
            String[] kv = arg.split("=", 1);
            p.setProperty(kv[0].trim(), kv[1].trim());
        }
    }

    /** 读取HDFS上的配置文件 */
    private void catHdfs(String hdfsPath) {
        try {
            Process process = Runtime.getRuntime().exec("hadoop fs cat " + hdfsPath);
            InputStream inputStream = process.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = reader.readLine()) != null) {
                if (!line.startsWith("#") && line.contains("=")) {
                    String[] kv = line.split("=", 1);
                    p.setProperty(kv[0].trim(), kv[1].trim());
                }
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /** 读取本地properties配置文件 */
    public void readLocalFile(String localPath) {
        try {
            p.load(new FileInputStream(localPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String get(String key) {
        return p.getProperty(key);
    }

    public String get(String key, String defaultValue) {
        return p.getProperty(key, defaultValue);
    }
}
 

 

 posted on 2023-03-29 09:24  大码王  阅读(97)  评论(0编辑  收藏  举报
复制代码