2020-12-20-python2.x和python3.x对比
print函数、字符串编码、除法、range和xrange、不等运算符、数据类型、文件操作、兼容2.x和3.x的案例
print函数
1)python2
print 2
2)python3
print(3)
字符串编码
1)python2
ASCii类型
2)python3
utf8
除法
1)floor除法//
python2和python3一致
2)一般除法/
python2中,对于整数相除,结果中会把小数点后的值忽略
python3中,对于整数相除,会先将两个整数转换成浮点数,再进行相除, 结果是浮点数
range和xrange
两者功能相似,python2中主要是xrange(迭代器实现),python3中主要是range
不等运算符
1)python2
可以用《》
和!=
表示
2)python3
只可以用!=
数据类型
1)python3中去掉了long类型,只有int
2)python2的bytes类型和str无区别
3)python3中dic的keys(),items,values返回的是一个迭代器;iterkeys()被废弃,dic.has_key()用in替代
文件操作
1)打开文件
python2
if __name__ == "__main__":
f = open("C:\Users\zhanghuan\Desktop\\123.txt",mode="r")
lines = f.readlines()
print lines
f.close()
注意:不可以有encoding="utf8",会报错
python3
if __name__ == "__main__":
f = open("C:\\Users\\zhanghuan\\Desktop\\123.txt",mode="r",encoding="utf8")
lines = f.readlines()
print(lines)
f.close()
2)输入
python2
if __name__ == "__main__":
a = raw_input()
print a
python3
if __name__ == "__main__":
a = input()
print(a)
兼容2.x和3.x的案例
# -- coding: utf-8 --
import logging
import json,os,re,socket,urllib,time,threading
IS_PYTHON2=True
try:
# python2.X
import BaseHTTPServer,urllib2,sys
from urllib import quote
from urlparse import urlparse
from urlparse import parse_qs
#from io import open
BaseHTTPRequestHandler = BaseHTTPServer.BaseHTTPRequestHandler
HTTPServer = BaseHTTPServer.HTTPServer
try:
reload(sys)
sys.setdefaultencoding("utf8")
except Exception as e:
print(e)
except Exception as e:
print(e)
print("当前python3.x环境")
IS_PYTHON2=False
# python3.x
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse
from urllib.parse import parse_qs
from urllib.request import urlopen
from urllib.parse import quote
class LogFactory():
rdir = os.path.dirname(os.path.abspath(__file__)) # 获取上级目录的绝对路径
log_dir = rdir + os.sep +'log'
log_file_dir = log_dir + os.sep + 'record.log'
@classmethod
def check_dirs(self):
if not os.path.exists(self.log_dir):
os.mkdir(self.log_dir)
if not os.path.exists(self.log_file_dir):
if not IS_PYTHON2:
fd = open(self.log_file_dir, mode="w",encoding='utf-8')
else:
fd = open(self.log_file_dir, mode="w")
fd.close()
@classmethod
def get_logger(self):
LogFactory.check_dirs()
fh = logging.FileHandler(self.log_file_dir, encoding='utf-8') # 创建一个文件流并设置编码utf8
logger = logging.getLogger() # 获得一个logger对象,默认是root
logger.setLevel(logging.DEBUG) # 设置最低等级debug
fm = logging.Formatter("%(asctime)s --- %(message)s") # 设置日志格式
logger.addHandler(fh) # 把文件流添加进来,流向写入到文件
fh.setFormatter(fm) # 把文件流添加写入格式
return logger
# 请求对象
class Request():
path = None
queries = None
body = None
headers = None
def __init__(self,obj):
if not IS_PYTHON2:
pathObj = urlparse(obj.path)
self.path = pathObj.path
self.queries = self.__handleQueriesToStandardMap(parse_qs(pathObj.query))
self.headers = obj.headers
if obj.headers['content-length'] != None:
self.body = obj.rfile.read(int(obj.headers['content-length']))
else:
pathObj = urlparse(obj.path)
self.path = pathObj.path
self.queries = self.__handleQueriesToStandardMap(parse_qs(pathObj.query))
self.headers = obj.headers
data_lenth = self.headers.getheader('content-length', 0)
if data_lenth != None:
self.body = obj.rfile.read(int(data_lenth))
# 将{key,['value']}转换成{key,value}
def __handleQueriesToStandardMap(self,map):
new_map = {}
for item in map.keys():
new_map.__setitem__(item,map.get(item)[0])
return new_map
# 响应对象
class Response():
obj = None
def __init__(self,obj):
self.obj = obj
def do_response(self,byte_data):
self.obj.send_response(200)
self.obj.send_header("Content-Type", "text/json;charset=UTF-8")
self.obj.end_headers()
self.obj.wfile.write(byte_data)
class ProperitesUtil():
@classmethod
def load_from_file(self,filepath):
properties = {}
with open(filepath,'r') as f:
for line in f:
if line.find('=') > 0:
strs = line.replace('\n', '').split('=')
properties[strs[0]] = strs[1].replace("\r","")
return properties
class NacosService():
base_dir = os.getcwd()
cfg = ProperitesUtil.load_from_file("%s%sconfig.properties"%(base_dir,os.sep))
# 发出心跳
def beat_to_nacos(self):
nacos_ip = self.cfg.get("nacosAddr")
local_ip = self.get_local_ip()
port = self.cfg.get("serverPort")
beat_arg = {"cluster": "c1", "ip": local_ip, "metadata": {}, "port": int(port), "scheduled": "true",
"serviceName": "nginx", "weight": 1}
beat_ip = 'http://%s/nacos/v1/ns/instance/beat?serviceName=nginx&beat=%s' % (nacos_ip,quote(str(beat_arg)))
while True:
if IS_PYTHON2 == False:
request = urllib.request.Request(url=beat_ip, method="PUT")
try:
urlopen(request)
print("beat to nacos success", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
time.sleep(5)
except Exception as e:
print("nacos connect failure")
print(e)
time.sleep(5)
print("trying to connect to " + beat_ip + " again ……")
else:
try:
request = urllib2.Request(beat_ip)
request.get_method = lambda:"PUT"
opener = urllib2.build_opener(urllib2.HTTPHandler)
opener.open(request)
print("beat to nacos success", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
time.sleep(5)
except Exception as e:
print("nacos connect failure")
print(e)
time.sleep(5)
print("trying to connect to " + beat_ip + " again ……")
# 获取本机ip
def get_local_ip(self):
# 获取配置文件中的信息
ip = self.cfg.get("preferred-networks")
if not self.valid_ip(ip):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
ip = s.getsockname()[0]
return ip
# 验证ip的合法性
def valid_ip(self,address):
try:
socket.inet_aton(address)
result = re.findall("\d+\.\d+\.\d+\.\d+",address)
if len(result) == 0:
return False
else:
return True
except:
return False
class MainHandler(BaseHTTPRequestHandler):
base_dir = os.getcwd()
log = LogFactory.get_logger()
def do_GET(self):
req = Request(self)
res = Response(self)
self.log.info("access " + req.path)
if req.path == "/https/disable":
# 关闭ssl
cfg = ProperitesUtil.load_from_file("%s%sconfig.properties"%(base_dir,os.sep))
if os.path.exists(cfg.get("sslConfDir")):
os.remove(cfg.get("sslConfDir"))
res.do_response(self.dic_to_bytes({"status":200}))
else:
err_msg = "未定义该路径"
self.log.info(err_msg)
res.do_response(self.dic_to_bytes({"status": 500,"msg":err_msg}))
def do_POST(self):
req = Request(self)
res = Response(self)
self.headers
self.log.info("access " + req.path)
if req.path == '/https/enable':
# 开启ssl
cfg = ProperitesUtil.load_from_file("%s%sconfig.properties"%(base_dir,os.sep))
data = json.loads(req.body)
print(data)
# 获取ssl端口
port_num = data['port']
# 获取ssl_certificate_file_name
ssl_certificate = data['ssl_certificate']
ssl_certificate_file_name = None if ssl_certificate =="" else "server" + ".crt"
# 获取ssl_certificate_key_file_name
ssl_certificate_key = data['ssl_certificate_key']
ssl_certificate_key_file_name = None if ssl_certificate_key =="" else "server" + ".key"
# 获取ssl_client_certificate_file_name
ssl_client_certificate = data['ssl_client_certificate']
ssl_client_certificate_file_name = None if ssl_client_certificate == "" else "CA" + ".crt"
# 操作nginx配置文件
modify_config_file = self.modify_config_file(ssl_certificate_file_name,
ssl_certificate_key_file_name,
ssl_client_certificate_file_name,port_num)
print(ssl_certificate_file_name,ssl_certificate_key_file_name,ssl_client_certificate_file_name)
if modify_config_file:
# 写入密钥文件
server_crt_path = cfg.get("nginxConfDir") + os.sep + "server.crt"
server_key_path = cfg.get("nginxConfDir") + os.sep + "server.key"
CA_crt_path = cfg.get("nginxConfDir") + os.sep + "CA.crt"
self.write_to_file(server_crt_path,str(ssl_certificate))
self.write_to_file(server_key_path, str(ssl_certificate_key))
if ssl_client_certificate_file_name != None:
self.write_to_file(CA_crt_path, str(ssl_client_certificate))
res.do_response(self.dic_to_bytes({"status":200}))
else:
err_msg = "出错了,可能原因:模板https配置文件不存在,传过来的参数不正确"
self.log.info(err_msg)
res.do_response(self.dic_to_bytes({"status": 500,"msg":err_msg}))
else:
err_msg = "未定义该路径"
self.log.info(err_msg)
res.do_response(self.dic_to_bytes({"status": 500,"msg":err_msg}))
def do_PUT(self):
req = Request(self)
res = Response(self)
err_msg = "未定义该路径"
self.log.info(err_msg)
res.do_response(self.dic_to_bytes({"status": 500, "msg": err_msg}))
def do_DELETE(self):
req = Request(self)
res = Response(self)
err_msg = "未定义该路径"
self.log.info(err_msg)
res.do_response(self.dic_to_bytes({"status": 500, "msg": err_msg}))
def dic_to_bytes(self,dic):
if not IS_PYTHON2:
return bytes(json.dumps(dic), encoding="utf8")
else:
return bytes(json.dumps(dic)).encode("utf8")
# 内容指定路径写入到文件
def write_to_file(self,filename,content):
if IS_PYTHON2:
f1 = open(filename, mode='w')
content = content.decode('utf8')
else:
f1 = open(filename, mode='w', encoding='utf8')
f1.writelines(content)
f1.close()
def write_to_file_from_list(self,filename,list):
if not IS_PYTHON2:
with open(filename,mode='w',encoding="utf8") as f:
for item in list:
f.write(item)
else:
with open(filename,mode='w') as f:
for item in list:
f.write(item)
def read_from_file(self,filename):
if not IS_PYTHON2:
with open(filename, 'r', encoding='utf8') as f:
return f.readlines()
else:
with open(filename,'r') as f:
return f.readlines()
# 操作nginx配置文件
def modify_config_file(self,ssl_certificate_file_name,ssl_certificate_key_file_name,ssl_client_certificate_file_name,port_num):
# 参数检验
if ssl_certificate_file_name == None or ssl_certificate_key_file_name == None or port_num == None:
self.log.error("ssl_certificate_file_name,ssl_certificate_key_file_name,port_num"+"参数不合法")
return False
# 获取配置文件中的信息
cfg = ProperitesUtil.load_from_file("%s%sconfig.properties"%(base_dir,os.sep))
# 获取nginx配置文件模板路径
template_https_conf_diir = "%s%stemplate%shttps.conf"%(self.base_dir,os.sep,os.sep)
# 获取nginx配置文件路径
https_conf_dir = cfg.get("sslConfDir")
# 如果路径不存在,返回False
if not os.path.exists(template_https_conf_diir):
self.log.error("template_https_conf_diir路径不存在")
return False
# 将配置文件内容读取出来并替换
content = self.read_from_file(template_https_conf_diir)
for i in range(len(content)):
ssl_certificate = re.findall("ssl_certificate\s+\w+\.\w+", content[i])
ssl_certificate_key = re.findall("ssl_certificate_key\s+\w+\.\w+", content[i])
ssl_client_certificate = re.findall("ssl_client_certificate\s+\w+\.\w+", content[i])
port = re.findall("listen\s+\d+\s+ssl", content[i])
# 标记
mark = -1
if len(ssl_certificate) != 0:
content[i] = content[i].replace(ssl_certificate[0], "ssl_certificate "+ssl_certificate_file_name)
if len(ssl_certificate_key) != 0:
content[i] = content[i].replace(ssl_certificate_key[0], "ssl_certificate_key "+ssl_certificate_key_file_name)
mark = i+1
if mark != -1 and ssl_client_certificate_file_name != None:
content.insert(mark," ssl_client_certificate "+ssl_client_certificate_file_name+"\n")
mark = -1
if len(port) != 0:
content[i] = content[i].replace(port[0], "listen "+str(port_num)+" ssl")
# 将修改后的配置文件写入
self.write_to_file_from_list(cfg.get("sslConfDir"),content)
return True
if __name__ == '__main__':
# 获取配置文件
base_dir = os.getcwd()
cfg = ProperitesUtil.load_from_file("%s%sconfig.properties"%(base_dir,os.sep))
port = cfg.get("serverPort")
# 开启一个线程发出心跳
nacosService = NacosService()
t = threading.Thread(target=nacosService.beat_to_nacos)
t.daemon = True
t.start()
server = HTTPServer(("0.0.0.0",int(port)), MainHandler)
print("The server is already started at " + port)
server.serve_forever()
config.properties
# 端口号
serverPort=8088
# 放置证书的地址,在nginx的conf目录下
nginxConfDir=C:\Users\zhanghuan\Desktop\test
# https相关的配置文件地址
sslConfDir=C:\Users\zhanghuan\Desktop\test\https.conf
# nacos服务的地址
nacosAddr=10.0.248.94:8848
# 本机ip,可不指定
preferred-networks=
另外创建一个template文件夹,放入nginx的https配置文件模板