文章目录
1 基础知识2 读取配置文件3 改写配置文件3.1 删除section3.2 字符串大小写问题4 实例4.1 1维两层的数据4.2 多维两层的数据4.3 使用am运行得到的文件参考文献:
【1】python读取配置文件&&简单封装
【2】python 中使用ConfigParser类修改配置文件
【3】python3中的RE(正则表达式)-总结
1 基础知识
python里面需要使用到configparser
包,可以使用pip安装
pip install configparser
在配置文件里面,默认使用[ ]
表示section,如下config.ini
文件表示有两个节:
[user1]user_ip = 127.0.0.1user_name = testuser1user_id = 45[user2]user_ip = 127.0.0.2user_name = testuser2user_id = 41
2 读取配置文件
下面代码有注释,关于使用os写相对路径,可以看参考文献【1】
import configparsercf = configparser.ConfigParser()cf.read("config.ini") # 读取配置文件,如果写文件的绝对路径,就可以不用os模块secs = cf.sections() # 获取文件中所有的section(一个配置文件中可以有多个配置,如数据库相关的配置,邮箱相关的配置,# 每个section由[]包裹,即[section]),并以列表的形式返回print(secs)options = cf.options("user1") # 获取某个section名为user1所对应的键print(options)items = cf.items("user1") # 获取section名为user1所对应的全部键值对print(items)name = cf.get("user1", "user_name") # 获取user1中user_name对应的值print(name)
3 改写配置文件
已知原始config.ini
文件如下
[user1]user_ip = 127.0.0.1user_name = testuser1user_id = 45[user2]user_ip = 127.0.0.2user_name = testuser2user_id = 41
写一个write_config.py
来更改配置文件
import configparserimport numpy as npimport copyconf = configparser.ConfigParser()filename = "config.ini"conf.read(filename)node = "user1" #改user1key = "user_id"value = "00"conf.set(node, key, value)fh = open(filename, 'w')conf.write(fh) # 把要修改的节点的内容写到文件中fh.close()
更新:
上面的写入文件代码
fh = open(filename, 'w')conf.write(fh) # 把要修改的节点的内容写到文件中
可能在某些文件中最后一行会有问题,所以将之改为(下面所有代码都这么改即可)
with open('config.txt', 'w') as configfile:conf.write(configfile)
运行此文件之后,发现配置文件变了
[user1]user_ip = 127.0.0.1user_name = testuser1user_id = 00 #改为00[user2]user_ip = 127.0.0.2user_name = testuser2user_id = 41
使用for循环将两个user同时改
import configparserimport numpy as npimport copyconf = configparser.ConfigParser()filename = "config.ini"conf.read(filename)secs = conf.sections()user_ip = ['192.168.0','192.168.1']user_name = ['python','python1']user_id = ['111','222']ip_key = 'user_ip'name_key = 'user_name'id_key = 'user_id'for i in range(len(secs)):conf.set(secs[i], ip_key,user_ip[i])conf.set(secs[i], name_key, user_name[i])conf.set(secs[i], id_key, user_id[i])fh = open(filename, 'w')conf.write(fh) fh.close()
当然,conf.set可以直接指定字段,不用重命名
import configparserimport numpy as npconf = configparser.ConfigParser()filename = "config.ini"conf.read(filename)secs = conf.sections()user_ip = ['192.168.0','192.168.1']user_name = ['python','python1']user_id = ['111','222']for i in range(len(secs)):conf.set(secs[i], 'user_ip', user_ip[i])conf.set(secs[i], 'user_name', user_name[i]) #直接指定字段conf.set(secs[i], 'user_id', user_id[i])fh = open(filename, 'w')conf.write(fh) fh.close()
结果为
[user1]user_ip = 192.168.0user_name = pythonuser_id = 111[user2]user_ip = 192.168.1user_name = python1user_id = 222
以上都是没有写成类的,要写成类的形式可以看参考文献【1】
3.1 删除section
config.remove_option('user1', 'user_ip')# 删除user1分组的user_ipconfig.remove_section('user1')# 删除配置文件中user1分组(会将整个user1下的ip,id,name都删除)
更多关于config的使用可以看官网
现在有另一个需求:将修改后的配置文件保存到一个名为config.txt
的文件中,并去掉中括号内的字符,即去掉[user1],[user2]
上面的代码,实际上修改完之后通过open可以写入到新文件中(原文件的内容不会改变)
for i in range(len(secs)):conf.set(secs[i], 'user_ip', user_ip[i])conf.set(secs[i], 'user_name', user_name[i]) #直接指定字段conf.set(secs[i], 'user_id', user_id[i])#fh = open(filename, 'w')fh = open('config.txt','w') #文件另存到config.txt中conf.write(fh) fh.close()
现在需要将[user1],[user2]
字段去掉,一个方法是将它们替换为空。比如这里将[user2]
改为空,即``,注意不是表示的空格,而是none。
import configparserimport numpy as npconf = configparser.ConfigParser()filename = "config.ini"conf.read(filename)secs = conf.sections()user_ip = ['192.168.0','192.168.1']user_name = ['python','python1']user_id = ['111','222']for i in range(len(secs)):conf.set(secs[i], 'user_ip', user_ip[i])conf.set(secs[i], 'user_name', user_name[i]) #直接指定字段conf.set(secs[i], 'user_id', user_id[i])#fh = open(filename, 'w')fh = open('config.txt','w') #文件另存到config.txt中conf.write(fh) fh.close()#将[user2]去掉with open('config.txt', 'r') as fpr:content = fpr.read()content = content.replace('[user2]', '')with open('config.txt', 'w') as fpw: #如果要另存为a.txt,则将config.txt改为a.txtfpw.write(content)
结果如下
另外,可以使用正则表达式
import re# read filef1 = open('config.txt','r')f2 = open('a.txt','w')# write filefor ss in f1.readlines():a = re.sub(r'\[user2\]','',ss)f2.write(a)f1.close()f2.close()
上面需要注意,正则表达式如果没有斜杠,\[user\]
,会表示将所有的user都换掉,包括user_id
等里面的user字符都去掉。那么既然使用了正则表达式,就可以将user1,user2同时去掉了,可以规定但凡有[user*
的都去掉(*
表示后面所有)或者但凡user
后有数字接着的都去掉。这部分可以看参考文献【3】
所以只需要将上面的代码改为:
# read filef1 = open('config.txt','r')f2 = open('a.txt','w')# write filefor ss in f1.readlines():a = re.sub(r'\[user\d\]','',ss) #\d表示匹配0-9数字f2.write(a)f1.close()f2.close()
结果为
至此,完整代码如下:
import configparserimport numpy as npimport reconf = configparser.ConfigParser()filename = "config.ini"conf.read(filename)secs = conf.sections()user_ip = ['192.168.0','192.168.1']user_name = ['python','python1']user_id = ['111','222']for i in range(len(secs)):conf.set(secs[i], 'user_ip', user_ip[i])conf.set(secs[i], 'user_name', user_name[i]) #直接指定字段conf.set(secs[i], 'user_id', user_id[i])with open('config.txt', 'w') as configfile:conf.write(configfile)configfile.close()# read filef1 = open('config.txt','r')f2 = open('a.txt','w')# write filefor ss in f1.readlines():a = re.sub(r'\[user\d\]','',ss)f2.write(a)f1.close()f2.close()
3.2 字符串大小写问题
源包configparser中设置的输出都是小写的,比如把上面例题中的user_ip
改为User_ip
,即首字母大写,结果运行完之后得到的却依然是user_ip
这是因为在configparser包中定义的输出为小写
def optionxform(self, optionstr):return optionstr.lower()#转小写字母
因此我们可以自己写一个函数,替换掉optionxform,即
import configparserclass Myconf(configparser.ConfigParser):def __init__(self, defaults=None):configparser.ConfigParser.__init__(self, defaults=None) #继承父类def optionxform(self, optionstr):return optionstr #没有改为小写conf = Myconf()
4 实例
这是本人需要解决的一个问题,不感兴趣的读者可以不往下看了,仅作为笔者笔记使用
4.1 1维两层的数据
相当于望远镜只朝天上看一个方向,这个方向上把水汽分成两层,每层得到一组数据
即数据如下:
Pbase = ['542', '542']Tbase = ['268.6', '268.6']column_h2o_vmr = ['5.49e-04', '5.49e-04']column_o3_vmr = ['4.38e-08', '4.38e-08']
具体过程如下:
现在有一个名为onelayer.amc的文件
即
? Example:? am test.amc 0 GHz 300 GHz 10 MHz 0 deg?f %1 %2 %3 %4 %5 %6output f GHz Tb Kjacobian Tbza %7 %8tol 1e-4Nscale troposphere h2o 1.0T0 2.7 Klayer tropospherePbase 542 mbar Tbase 368.6 K column dry_air vmrcolumn h2o vmr 5.49e-04column o3 vmr 4.38e-08layer tropospherePbase 542 mbar Tbase 368.6 K column dry_air vmrcolumn h2o vmr 5.49e-04column o3 vmr 4.38e-08
现在需要对其修改layer troposphere下面的Pbase
,Tbase
等参数,使用configparser。(我相信肯定有更好的办法,欢迎留言)
首先要修改onelayer.amc文件到config.ini中,如下(注意配置文件一定是xx=yy的形式,没有=
会报错的,所以临时修改了一些量,使得都含有=号,最后再想办法用正则表达式去掉=号即可)
[layer 2]layer=tropospherePbase=542 mbarTbase=268.6 K column_dry_air=vmrcolumn_h2o_vmr=5.49e-04column_o3_vmr=4.38e-08[layer 1]layer=tropospherePbase=542 mbarTbase=268.6 K column_dry_air=vmrcolumn_h2o_vmr=5.49e-04column_o3_vmr=4.38e-08
然后在需要最后写入的文件a.txt中将前面部分不需要改动的写进去,之后在写入每个layer troposphere的时候通过追加的形式。
? Example:? am test.amc 0 GHz 300 GHz 10 MHz 0 deg?f %1 %2 %3 %4 %5 %6output f GHz Tb Kjacobian Tbza %7 %8tol 1e-4Nscale troposphere h2o 1.0T0 2.7 K
所以所有的文件大概关系是
运行write_config.py
得到a.txt文件为:
源码如下
import configparserimport numpy as npimport reclass Myconf(configparser.ConfigParser):def __init__(self, defaults=None):configparser.ConfigParser.__init__(self, defaults=None)def optionxform(self, optionstr):return optionstrconf = Myconf()filename = "config.ini"conf.read(filename)secs = conf.sections()Pbase = ['542', '542']Tbase = ['268.6', '268.6']column_h2o_vmr = ['5.49e-04', '5.49e-04']column_o3_vmr = ['4.38e-08', '4.38e-08']for i in range(len(secs)):conf.set(secs[i], 'Pbase', Pbase[i]+' mbar') #加入单位mbarconf.set(secs[i], 'Tbase', Tbase[i]+' K') #直接指定字段conf.set(secs[i], 'column_h2o_vmr', column_h2o_vmr[i])conf.set(secs[i], 'column_o3_vmr', column_o3_vmr[i])#文件另存到config.txt中with open('config.txt', 'w') as configfile:conf.write(configfile)configfile.close()# read filef1 = open('config.txt','r')f2 = open('a.txt','a') #追加的形式# write filefor ss in f1.readlines():ss = re.sub(r'\[layer \d\]','',ss)ss = re.sub('layer = troposphere', 'layer troposphere',ss)ss = re.sub(r'base =',r'base',ss)ss = re.sub('column_dry_air = vmr', 'column dry_air vmr',ss)ss = re.sub('column_h2o_vmr =', 'column h2o vmr', ss)ss = re.sub('column_o3_vmr =', 'column o3 vmr', ss)f2.write(ss)f1.close()f2.close()
4.2 多维两层的数据
相当于望远镜只朝天上看一个方向,这个方向上把水汽分成两层,每层得到一组数据;然后移动望远镜一定的距离又得到另一个方向上的数据。
Pbase = [['542', '500'],['530','480']] #二维数据,每个维度表示一个方向上的点Tbase = [['268.6','250'], ['265','258']]column_h2o_vmr = [['5.49e-04','5.41e-04'], ['5.43e-04','5.40e-04']]column_o3_vmr = [['4.4e-08','4.3e-08'],['4.50e-08', '4.38e-08']]
具体过程如下:
我们现在要把每个方向上观测到的点放入单个文件中,即一个文件表示一个方向。
首先我们要把前缀部分统一写入多个文件,以两个方向为例,即两个文件
先建立一个只有前缀的prefix.amc文件
将上面的文件写入每个文件中,即写入a0.amc, a1.amc中,相当于拷贝
#write prefix to files:for j in range(len(Pbase)):prefix_file = open('prefix.amc', 'r')f0 = open('a'+str(j)+'.amc','w')text = prefix_file.read()f0.write(text)f0.close()prefix_file.close()
然后就可以开始上面同样的过程了(这里我把for放一起了),完整代码如下:
import configparserimport numpy as npimport reclass Myconf(configparser.ConfigParser):def __init__(self, defaults=None):configparser.ConfigParser.__init__(self, defaults=None)def optionxform(self, optionstr):return optionstrconf = Myconf()filename = "config.ini"conf.read(filename)secs = conf.sections()Pbase = [['542', '500'], ['530', '480']] # 二维数据,每个维度表示一个方向上的点Tbase = [['268.6', '250'], ['265', '258']]column_h2o_vmr = [['5.49e-04', '5.41e-04'], ['5.43e-04', '5.40e-04']]column_o3_vmr = [['4.4e-08', '4.3e-08'], ['4.50e-08', '4.38e-08']]#write prefix to files:for j in range(len(Pbase)):prefix_file = open('prefix.amc', 'r')f0 = open('a'+str(j)+'.amc','w')text = prefix_file.read()f0.write(text)f0.close()prefix_file.close()for j in range(len(Pbase)):for i in range(len(secs)):conf.set(secs[i], 'Pbase', Pbase[j][i]+' mbar') #加入单位mbarconf.set(secs[i], 'Tbase', Tbase[j][i]+' K') #直接指定字段conf.set(secs[i], 'column_h2o_vmr', column_h2o_vmr[j][i])conf.set(secs[i], 'column_o3_vmr', column_o3_vmr[j][i])#文件另存到config.txt中with open('config'+str(j)+'.txt', 'w') as configfile:conf.write(configfile)configfile.close()f1 = open('config'+str(j)+'.txt', 'r')f2 = open('a'+str(j)+'.amc', 'a')# write filefor ss in f1.readlines():ss = re.sub(r'\[layer \d\]', '', ss)ss = re.sub('layer = troposphere', 'layer troposphere', ss)ss = re.sub(r'base =', r'base', ss)ss = re.sub('column_dry_air = vmr', 'column dry_air vmr', ss)ss = re.sub('column_h2o_vmr =', 'column h2o vmr', ss)ss = re.sub('column_o3_vmr =', 'column o3 vmr', ss)f2.write(ss)f2.close()f1.close()
得到两个文件,a1.amc如下
4.3 使用am运行得到的文件
这部分由于要使用am
在终端运行,所以得要借助shell命令,
参考shell运行文件
建立一个名为run.sh的文件,内容为:
由于间隔是2GHz,所以只会输出100GHz对于的值
补充:上面的的>
表示输出到文件,而如果使用>>
则表示追加,即在原文件后累加。
如我将上面的>改为>>,则得到的结果如下:
现在有两个文件a0.amc, a1.amc所以需要使用for循环,参考另一博文
因为采用的是seq
这种for循环,必须从1开始(尝试了其他的循环都没有效果)
所以对上面一开始的文件做如下处理:
1)将文件a0.amc改为a2.amc2)由于am运行的时候底下最低的一层Pbase似乎是要大于550 mbar,所以将值改为大于550的任意值即可
现在开始写run.sh文件
使用追加的形式,将运行结果统一放置在a.out中,运行结束会输出done
运行run.sh,有两种方法
1,直接sh运行
sh run.sh
2, 给定权限之后运行
chmod +x run.sh./run.sh
得到结果