用python类的形式怎样做管理系统-Python配置管理的几种方式

Python09

用python类的形式怎样做管理系统-Python配置管理的几种方式,第1张

一、 为什么要使用配置

如果我们在较复杂的项目中不使用配置文件,我们可能会面临下面的情况:

你决定更改你的项目中数据库的 host, 因为你要将项目从测试环境转移到实际的生产环境中。如果你的项目中多个位置用到了这个 host,那你不得不一个一个找到这些位置再修改成新的 host。花了半天,然后过了一天,你发现项目在生产环境有些问题,需要重新移回测试环境,你得再次修改,这样工作很繁琐很不优雅。

你开发了一个很棒的开源项目,你想将其放到版本控制系统例如github上,但是你服务器的主机的地址、账号、密码也都上传上去了,但是你没有意识到,直到有个 bad guy 拿到了你的信息,从你的服务器窃取信息、攻击你的服务器,让你产生了极大的损失。然后你想把程序改动一下,把涉密的信息比如地址密码都删掉,可是由于版本控制的原因,别人依然能看到你以前版本的代码。于是你不得不改掉你的账户、密码等,真的是个悲伤的开源项目经历。

但是,如果你使用了配置管理呢,那会有以下几个优点:

这样就提高了代码的重用性,不再每次都去修改代码内部

这意味着其他不太懂你代码内部的人也可以使用你的项目,只用根据需求更改配置即可

有利于团队协作

有利于安全数据/秘密数据的管理

二、Python 中进行配置管理的几种方式

由于使用 Python 较多,因此基于 Python 进行配置管理的相关说明,当然其他语言也都是大同小异,主要思想还是不变。

2.1 使用 Python 内置的数据结构(如字典)

2.1.1单个文件下的单个配置

我们很自然就能想到这一点,例如以下代码:

在上面的代码中,我们可以看到,同一数据库配置,我们反复使用了两次,如果我们需要更改数据库相关的数据如password,我们不需要在两个方法内部修改,而是只用修改DATABASE_CONFIG字典中的相关值即可。和以前没有配置管理的时候相比,减少了太多的工作量了。

2.1.2多个文件下的单个配置

但是当你的项目开始变得复杂的时候,你的文件就不止一个这么简单了,这时候如果我需要在 main2.py 里面需要用 DATABASE_CONFIG 的时候就不是很方便了,因为如果直接 import main 的时候,虽然能够使用 main.DATABASE_CONFIG ,但同时 mian.py 中的

也被执行了,这可不是我们想看到的,因此我们有了新的需求,能在同一个项目下的不同文件里简单快速的导入我们的数据库配置 DATABASE_CONFIG,于是我们想出了下面的方法来解决这个问题:

按照上面的代码,我们可以在两个不同的文件 main1.py 和 main2.py 中分别引用 config.py 中配置了,我们的配置管理看起来更进一步了。

2.1.3 单个文件下的多个配置

有可能我们的项目需要多个配置文件,比如测试环境和生产环境。先从单个文件讲起,我们可以采用如下解决方案:

这样我们就可以从一个配置文件中获取不同级别的不同配置了。

2.1.4 多个文件下的多个配置

和上面类似,只不过换成了从不同的文件中读取同一个配置文件的不同配置:

这样使用更加灵活了,从不同的文件里读取不同的配置,而我们对于配置的增删改只需要在 config.py 中进行,配置管理技能再次进阶!

2.2 使用外部配置文件

比起使用 Python 内建的数据结构,更加通用的方法是使用外部配置文件,因为这些文件只会被视为配置文件,而不会像 config.py 一样有代码的属性。外部配置文件的格式多种多样,我们在使用它的时候会根据文件格式有不同的读取方式。例如:*.yaml 或者 *.yml、*.json、*.cfg 或 *.conf 、*.ini , 甚至是你自定义的文件 *.yourname 。

2.2.1 YAML

YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达数据序列化的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、电子邮件的数据格式(RFC 2822)中获得灵感。Clark Evans在2001年首次发表了这种语言[1],另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者[2]。当前已经有数种编程语言或脚本语言支持(或者说解析)这种语言。

----- 中文维基百科

YAML 看起来像下面这种格式:

如果需要从 python 写入配置到 YAML 也很容易,只需要使用 yaml.dump(dict) 即可,dict 指的是配置的字典。更加详细的内容可以查看 PyYAML Documentation

2.2.2 INI

INI文件是一个无固定标准格式的配置文件。它以简单的文字与简单的结构组成,常常使用在Windows操作系统,或是其他操作系统上,许多程序也会采用INI文件做为设置程序之用。Windows操作系统后来以注册表的形式取代掉INI档。INI文件的命名来源,是取自英文“初始(Initial)”的首字缩写,正与它的用途——初始化程序相应。有时候,INI文件也会以不同的扩展名,如“.CFG”、“.CONF”、或是“.TXT”代替。

----- 中文维基百科

它长得像这样:

这将输出 INI 配置文件中的 mysql section 中的 host 值

要写入 INI 配置文件也很简单,参考如下代码即可:

2.2.3 JSON

JSON是JavaScript对象表示法的缩写。它非常广泛,因此对许多编程语言都有很好的支持。它的格式大家也很眼熟,看起来和 Python 中的字典很像:

要将配置写入json中也很简单,参考以下代码:

其他格式的文件大多如此,就不赘述了。并且外部的配置文件中也可以配置多个配置(mysql, other等)

2.3 使用环境变量

但是,回到我们开篇讲的问题,以上的两种配置管理方案(使用 Python 内置的数据结构、使用外部配置文件) 都忽略了两个问题:

其一,我们如何应对安全数据直接曝光于公众的可能问题呢,如果我们需要使用版本控制系统例如 Github,或许我们可以尝试将 config.py 文件放到 .gitignore 里面,但我们如果哪一天修改了仓库,忘了将 config.py 忽略掉而 push 到了GitHub 上,那么我们的安全敏感信息仍然会向公众泄露,由于版本控制的存在,即使你删掉了还会有这条提交记录,处理起来会很麻烦。

其二,如果我们要在我们本地新开一个项目,这个项目也需要引用一样的数据库配置文件,或许我们可以找到第一个项目的文件夹,复制出 config.py 到 新的项目文件夹。嗯,看起来可行,但是,如果你要新开十几个项目呢,几百个项目呢?

因此我们可以引入下一种配置管理的方式,对解决上面提出的两个问题都是较为友好的解决方案,即使用环境变量,各种开发环境(Win、Mac、Linux)的系统环境变量的设置方式有所不同,可以参考这篇文章。

另外 PyCharm 和 VS Code 有更加方便的配置方式,可以为不同的项目分配不同的设置。

PyCharm 中,在菜单 Run->Edit configurations 中,手动设置Environment variables

VS Code 中,在 Setting 中搜索 env ,在 Terminal 中选择你的操作系统相关的Terminal >Integrated >Env: Your OS ,点击 settings.json 进行添加

使用环境变量配置值不用作为单独的文件进行管理,因此有较小的安全风险,它很容易使用,可以在你的开发环境中的任何项目任何代码库中使用,但是它的管理方式可能有些复杂。有些环境无法使用环境变量,比如Apache,Nginx等Web服务器,这时候就需要采用其他的方式。

2.4 使用动态加载

这种方法比利用 Python 内置的数据结构更加先进,内置数据结构的方法要求配置文件必须要在可以直接 import 的路径上。但是动态加载中,配置文件不必在可直接导入的路径上,甚至可以位于其他存储库中,这样的话,配置文件就和项目分隔开了,其他的项目也可以动态加载这个配置文件,例如:

三、总结

以上归纳了四种配置管理的方式,总体来说没有优劣之分,看个人的需要,甚至上面的几种方法可以混合使用,对于一些软件项目,它自身可能就提供了相关的变量配置入口,比如 airbnb 的 Airflow 。而且,当系统规模非常大时,最好使用主要提供配置管理的第三方工具或服务,相关服务可以参考这里。

如何使用Python动态控制Linux系统的内存占用百分比?

近期有网上朋友寻求帮助:如何通过脚本动态控制Linux系统的内存占用百分比?经过一番百度+编写调试,终于初步完成了动态控制Linux系统内存占用百分比。现写出来以帮助更多的朋友。

1 前言

根据需求是动态控制Linux系统内存占用百分比,比如当前内存占用30%,如果设置内存占用为70%,则需要申请内存使达到占用70%;如果再降低到40%,则需要释放部分申请的内存。其实脚本的本质是内存动态申请与释放。

注意:因为Python脚本运行之前内存有一定占用,故设定内存占用不能低于该百分比。

2 内存动态申请

通过查询资料,使用Python动态申请内存块,可以使用ctypes包中的函数,导入包及代码如下所示:

>>>from ctypes import *

>>>mem=create_string_buffer(1024)

说明:内存申请使用create_string_buffer()函数,上面申请了1024字节的内存块。

下面演示申请100MB内存前后变化

申请前如下图所示:

使用代码如下:

>>>mem=create_string_buffer(104857600)

申请后如下图所示:

从上述两幅图中可以看出,申请内存前内存占用295MB,申请后内存占用397MB,增加了约100MB内存占用。

3 内存动态释放

由于Python对内存是有垃圾回收机制的,采用对象引用计数方式。当对象的引用计数为0时,启动垃圾回收GC。此处内存动态释放就是使用该原理。

代码如下:

>>>mem=None

释放后内存占用如下图所示:

内存占用由397MB降低到297MB,释放了100MB内存占用。

说明:将None赋值给对象mem后,mem对象的引用计数即为0,此时垃圾回收启动,释放mem对象占用的内存。

4 系统总内存、占用内存检测

由于需要设定内存占用百分比,故需要获取系统总物理内存和占用内存。本文使用的方法是读取系统文件“/proc/meminfo”,从中解析出总内存大小以及当前内存占用大小等内存相关的信息。该文件内容格式如下图所示:

代码片段如下所示:

f = open("/proc/meminfo")

lines = f.readlines()

f.close()

for line in lines:

if len(line)<2:continue

name = line.split(':')[0]

var = line.split(':')[1].split()[0]

mem[name]= long(var)* 1024.0

mem['MemUsed']= mem['MemTotal']- mem['MemFree']

说明:按行读取meminfo文件内容,创建字典对象mem,将meminfo文件第一列设置为mem对象的键值,将meminfo文件第二列数字设置为mem对象的值。

5 获取用户输入百分比

通过读取键盘输入字符串,然后转换为数字实现接收用户输入的百分比,代码如下所示:

input_str=raw_input("Input UsedMemory`s Rate or q to exit:")

rate=float(input_str)

注意:此处键盘输入的都是字符串,需要进行字符串转换为数字,使用float()或long()函数进行转换。

6 动态设置内存占用百分比测试

测试使用两个Python脚本文件,分别是test.py和mem_rate.py,其功能分别是查看当前内存占用和动态设定内存占用百分比。如下图所示:

注意:上述两个文件需要使用“chmod +x *.py”修改为可执行属性。

6.1 查看当前内存占用

查看当前内存占用百分比,使用上述test.py文件,运行命令为“./test.py”,运行结果如下图所示:

当前使用内存为320MB,占用百分比为17%。

6.2 动态设置内存占用百分比

动态设置内存占用百分比使用上述mem_rate.py脚本,注意该脚本文件第一行代码为“#!/usr/bin/python2.6”,表示该脚本使用python2.6程序运行。该行需要修改为待运行Linux系统中Python实际的安装程序路径。

动态内存百分比设置界面如下图所示:

处于待输入状态。另外显示了当前内存占用(321MB),总内存大小(1869MB)以及内存占用百分比(17%)。

如果此时设置内存占用百分比为80%,则脚本会每次申请10MB空间,直至内存占用接近或等于80%为止。如下图所示:

内存申请过程如下图所示:

内存申请过程中占用百分比变化为:35%,45%,56%,70%,…

mem_rate.py运行过程如下图所示:

内存申请过程中占用变化为:1461MB,1471MB,1481MB,1491MB。

此时如果内存占用百分比设置为20%,则需要释放一部分内存。

test.py脚本运行过程如下图所示:

由于释放内存运行较快,抓取到最后结果

内存占用为20%。

mem_rate.py脚本运行过程如下图所示:

内存释放过程中内存占用为:413MB,403MB,393MB,383MB,最后内存占用稳定在20%,383MB。

输入“q”或“Q”退出内存占用百分比设定过程,如下图所示:

此时内存占用如下图所示:

内存占用恢复到运行mem_rate.py脚本之前状态,17%,321MB。

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

附:完整Python脚本代码

test.py

------------------------------------------------------------------------------------------------

#!/usr/bin/python2.6

def memory_stat():

mem = {}

f = open("/proc/meminfo")

lines = f.readlines()

f.close()

for line in lines:

if len(line)<2:continue

name = line.split(':')[0]

var = line.split(':')[1].split()[0]

mem[name]= long(var)* 1024.0

mem['MemUsed']= mem['MemTotal']- mem['MemFree']

# - mem['Buffers']- mem['Cached']

return mem

mem=memory_stat()

print("Used(MB):%d"%(long(mem['MemUsed'])/1024/1024))

print("Rate:%d%%"%(100*long(mem['MemUsed'])/float(mem['MemTotal'])))

§§§§§§§§§§§§§§§§§§§§§§§§§§

mem_rate.py

---------------------------------------------------

#!/usr/bin/python2.6

from ctypes import *

# Get Memory Info(Total, Used... Byte)

def get_memory_stat():

mem = {}

f = open("/proc/meminfo")

lines = f.readlines()

f.close()

for line in lines:

if len(line)<2:continue

name = line.split(':')[0]

var = line.split(':')[1].split()[0]

mem[name]= long(var)* 1024.0

mem['MemUsed']= mem['MemTotal']- mem['MemFree']

# Return MemroyInfo Object

return mem

# Get Simple Memory Info

def get_memory_info(mem):

# Byte ->MB

n=1024* 1024

used=float(mem['MemUsed'])/ n

total=float(mem['MemTotal'])/ n

rate=used/total* 100

smp={'used':used,'total':total,'rate':rate}

return smp

# Display Current Memory Info

def print_memory_info(mem):

# Get SimpleMemory Info

smp=get_memory_info(mem)

print("Used(MB):%d\tTotal(MB):%d\tUsedRate:%d%%"%(smp['used'], smp['total'], smp['rate']))

# Get Rate Of Memory Used To Be Setted(Integer Formate)

def input_memory_used_rate(org_rate):

# Byte ->MB

n=1024* 1024

while(True):

mem=get_memory_stat()

print_memory_info(mem)

input_str=raw_input("Input UsedMemory`s Rate or q to exit:")

if(len(input_str)== 0):

continue

if("q"== input_str):

info={'rate':0,'used':mem['MemUsed']/ n}

return info

if("Q"== input_str):

info={'rate':0,'used':mem['MemUsed']/ n}

return info

try:

rate=float(input_str)

if((rate>=org_rate)and (rate<=95)):

info={'rate':rate,'used':mem['MemUsed']/ n}

return info

else:

print("Please inputa valid number(%d%%~95%%)."%(org_rate))

except:

print("Please inputa valid number(%d%%~95%%)."%(org_rate))

# Set Rate Of Memory Used

def set_memory_used_rate(new_rate, total, pre_used,list):

if(new_rate==0):

return None

dest_mem=total* new_rate /100.0

# 10MB

mb10=10485760

n_chg=10

# Free Memory OrAllocate Memory ?

is_new=dest_mem>pre_used

cur_used=pre_used

while(True):

# To Calc FreeMemory Or Allocate Memory ?

need_new=dest_mem-n_chg>=pre_used

need_del=dest_mem+n_chg<=pre_used

# Need To AllocateMemory

if(is_new):

if(need_new):

p=create_string_buffer(mb10)

list.append(p)

dest_mem=dest_mem-n_chg

cur_used=cur_used+n_chg

else:

return"end"

# Need To FreeMemory

else:

idx=len(list)-1

if(need_deland (idx>=0)):

p=list[idx]

del list[idx]

p=None

dest_mem=dest_mem+n_chg

cur_used=cur_used-n_chg

else:

return"end"

print("****** MemoryUsed(MB):%d"%(cur_used))

# Entry Of Program

# List Of Memory Object, 10MB Of One Object

list=[]

# Get Current Memory Info

mem=get_memory_stat()

# Get Simple Memory Info

smp=get_memory_info(mem)

org_rate=smp['rate']

total=smp['total']

while(True):

# Get Rate OfMemory To Be Used

info=input_memory_used_rate(org_rate)

new_rate=float(info['rate'])

pre_used=float(info['used'])

# Set Rate OfMemory To Be Used

rtn=set_memory_used_rate(new_rate, total, pre_used, list)

if(not rtn):

print("bye!")

exit()

控制系统库。

Python控制系统库是一个Python模块,该模块实现了用于分析和设计反馈控制系统的基本操作。

Python的标准库包括了很多的模块,从Python语言自身特定的类型和声明,到一些只用于少数程序的不著名的模块。