Python运维笔记 -- pipenv, jenkins, gitlab

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/duxiangwushirenfei/article/details/81088338

前言

两个月的漫游生活,迎来新的工作方向。些许辗转,本想能够从事AI相关工作,奈何缺乏相关工作经验,仅凭书中拾得微乎知识难以驾驭,进而转战运维开发。
第一项任务是打通自有平台和Jenkins,以实现在自有平台上能够完成CI/CD。
着手实现骤是觉得Python用作运维长处,对于jenkins,gitlab这种开放接口的工具,已有封装配套的Python包,安装调用即可。

版本管理 pipenv

先前的python 之版本控制 中介绍过pyenv和virtualenv,个人一直使用virtualenv,非常习惯和顺手。基本思路是需要使用某一版本的python解释器去官网上下载所需要版本,然后用virtualenv从该版本创建出所需的虚拟环境。所有的解释器都是笔者自己手动管理。而pipenv相当于集pyenv virtualenv于一身。完整信息参见pipenv官网

安装pipenv

# mac下可以brew
brew install pipenv
# 直接pip安装,避免和系统默认产生冲突
pip install --user pipenv
# 可以在机器的 .bashrc 中配置补全功能
eval "$(pipenv --completion)"

笔者直接用brew安装的,结果引来了很多麻烦,后面详述。
与virtualenv 相比,pipenv会自动去解析你当前目录下的 Pipfile文件,由此去安装依赖,配置进而取代requirements.txt的管理。但是pipenv仍然需要用户去下载不同的python解释器,如果你指定一个你本地没有的解释器来创建虚拟环境则会报出:

Warning: Python 3.7 was not found on your system
You can specify specific versions of Python with:
  $ pipenv --python path/to/python

使用

Pipfile文件的格式在官网中详细给出了,此处简单示例:

[[source]]
url = "https://mirrors.aliyun.com/pypi/simple"
verify_ssl = true
name = "pypi"

[packages]
requests = "*"

[dev-packages]
django = "*"

[requires]
python_version = "3.6"

在本地测试目录下依次执行:

# 创建虚拟env环境类似 virtualenv -p python3.6 
# 并且安装 Pipfile的包,并生成对应的Pipfile.lock文件
pipenv install
# 激活当前目录对应的env 
pipenv shell
# 安装package到当前evn中,同时会更新Pipfile,Pipfile.lock
pipenv install your_package
# 导出所安装的package信息到requirements.txt中
pipenv lock -r > requirements.txt
# 回归系统环境,用deactive终端显示上退出,实际也是退出,但再次pipenv shell 会显示当前终端已经激活了虚拟环境
exit

其实如果virtualenv如果使用的比较熟练,可以不必转用pipenv。自己手动管理所有的解释环境,在哪里,用哪个,心里都非常清楚。pipenv默认是在user的home目录下的 .local文件中创建了虚拟env环境,就是让版本控制更便捷。

出现问题

OSError

pipenv install初始化创建虚拟环境时如果如果出现了OSError导致失败,多数是ReadTimeoutError,在初次创建虚拟环境时候会去files.pythonhosted.org下载安装pip,setuptools等,如果网络不好丢包比较严重就会超时报错。

自动升级

笔者是brew install pipenv的,结果默认下载了python3.6的解释器安装了,出现了一个问题是系统全局python默认还是2.7,但是默认的pip是3.x(因为笔者原本机器上有几个python3.x的版本,且映射了bin/ 到PATH中)。恢复过程很是难受,不过倒是发现很多以前忽略的东西:
MacOS下系统python所在路径
/System/Library/Frameworks/Python.framework/Versions/ 所以如果想要恢复,核心问题在找到默认pip是指向何处的,然后通过修改连接,PATH去改变pip的搜寻顺序。

Linux Tips

which & whereis

是否遇到过 which a 命令有输出,但是whereis a 没有输出?
which 是搜寻你的命令 a 使用的是PATH中那个一路径下的命令。
whereis则搜寻的是user.cs_path,可以用sysctl user.cs_path 查看,二者是不一样的

PATH

修改PATH是很多时候经常做的事,当时笔者安装过几个版本的python3.x后就把其下属的bin/映射到PATH里了,问题是,PATH是有序的。echo ${path/''/'\n'} 查看其中的顺序就是使用命令a 时的搜寻顺序,先到先用。所以即便多个目录下有 pip命令,当笔者把安装的python3.x的bin/接在PATH前时,就会把全局pip不小心改成了python3.x下的。
export PATH=/usr/local/bin:$PATH
export PATH=$PATH:/usr/local/bin

此二者是不一样的。

docker volume 相对路径

先前碰到一个compose文件,没有多看就启动了其中的 pg,其data是映射到我本地的,结果我想找其挂载地址发现用的是相对路径。之前习惯默认是指定绝对的宿主机挂载路径,结果用相对路径找不到了。
docker inspect container_name 查看处的路径是CentOS下docker的容器路径。MacOS下根本没有
可以用
docker volume 相关命令操作这种相对路径创建的挂载
docker volume ls 查看列表
docker volume rm volume_name 删除

sz & rz

这是两个好东西,多数同学平时远程拷贝文件估计与笔者相同,用scp。但是如果是跳板机器转过去的呢?如果跳了不止一次呢?慢慢用 scp一步一步导出。。。如果是一个大点的文件,传一次10分钟,多跳几次。。。。。。
改用 szrz 吧。直接就从本地上传到,或者下载了,连scp基础的那些输入项都免了。
具体的安装配置过程就不详述了,item2上怎么配置随处可找。

Python

python-jenkins

python操作Jenkins的包,参见官网说明 。接口倒是挺全的,有些地方用起来也不难,就是返回的数据没找到文档,Jenkins官方是否提供笔者没找到。只能参照界面显示去看,比较费时。
笔者最难以忍受的是:

def jenkins_request(self, req, add_crumb=True, resolve_auth=True):
    try:
        if resolve_auth:
            self._maybe_add_auth()
        if add_crumb:
            self.maybe_add_crumb(req)

        return self._response_handler(
            self._request(req))

    except req_exc.HTTPError as e:
        # Jenkins's funky authentication means its nigh impossible to
        # distinguish errors.
        if e.response.status_code in [401, 403, 500]:
            raise JenkinsException(
                'Error in request. ' +
                'Possibly authentication failed [%s]: %s' % (
                    e.response.status_code, e.response.reason)
            )
        elif e.response.status_code == 404:
            raise NotFoundException('Requested item could not be found')
        else:
            raise
    except req_exc.Timeout as e:
        raise TimeoutException('Error in request: %s' % (e))
    except URLError as e:
        # python 2.6 compatibility to ensure same exception raised
        # since URLError wraps a socket timeout on python 2.6.
        if str(e.reason) == "timed out":
            raise TimeoutException('Error in request: %s' % (e.reason))
        raise JenkinsException('Error in request: %s' % (e.reason))

这里的 jenkins_request 是在执行 build_job操作时候,下两层调用的,也是这个包通用和jenkins交互的请求方法。这个方法里会抛出一个 Possibly authentication failed 异常。
这简直就是 坑爹到一定境地的做法。当时以为是在调用 build_job 构建时必须要传token,很多其他的地方对这个错也没详细说明。因为此前笔者测试调用build_job是成功的,但是后面死活不行,这种提示让笔者在用户认证这里转了n圈。
然后调试进入发现是上面抛出的,再看上面注释发发现这种异常是因为Jenkins's funky authentication means its nigh impossible to distinguish errors. 发生了一个不能辨别的错误。后面解决问题的方式是,从之前构建成功的构建中拉出信息对比,发现一个参数传入的不合法最后才发现是一个不合法额参数造成。
这里提供一种思路,往后如果碰到一个地方执行成功,而后不成功,不妨把成功的快照数据拉出来仔细对比,说不定就查处了问题
此外还有可能引发上述报错的是 create_job 指定的config_xml必须是 utf-8编码,否则也是上面额错误。总之,上述错误要依据具体调用方法查找,多数是参数引起的。

python-gitlab

python用以和gitlab交互的bao。首先gitlab官方给出了API文档 其中的说明非常详尽。
使用包的说明文档 也非常详尽。
例如Porject相关接口

projects = gl.projects.list()

只给出了几个参数,作为过滤条件,实际上,project是objects.ProjectManager(self) 实例,在定义中可以用作filter的参数很多,但是说明文档中没有给出,可以去gitlab的接口文档中查看,基本上都能满足需求。

_list_filters = ('search', 'owned', 'starred', 'archived', 'visibility',
                     'order_by', 'sort', 'simple', 'membership', 'statistics',
                     'with_issues_enabled', 'with_merge_requests_enabled',
                     'with_custom_attributes')

tips

函数注解

之前写函数习惯性是添加注释,其实还可以添加注解:

def func(x: int, y: callable) -> str:
    pass
# print结果{'x': <class 'int'>, 'return': <class 'str'>, 'y': <built-in function callable>}
print(add.__annotations__) 

这种形式,只是注解,是不会其他任何附加影响的,不会说你注解了x是int,传入str报错。Python是弱类型!!

函数参数

先前的函数基础知识说说过 *args,**kwargs两种参数,倘若要一个函数,其调用只能是关键字形式传入参数可以如下定义:

def func(*, x, y, **kwargs):
    pass
# 只能是关键字形式传入参数
func(x=1, y=2, option_param=3)

__str__ & __repr__

上次被人问到这两个,本来想这东西多数书上都有,但是还真有人问,那就说吧,一个是在python 的shell下直接裸给一个实例时调用,一个是print打印时调用。

>>>a = A()
# 调用__repr__
>>>a 
# 调用__str__
>>>print(a)


注意:
如果只定义了一个__repr__ 此时 裸给和print都调用__repr__
如果只定义了一个__str__,裸调返回内置默认的,即平时看到给出地址号的那种,print则调用__str__。

猜你喜欢

转载自blog.csdn.net/duxiangwushirenfei/article/details/81088338