python day 18

2019/10/29

1. thinking in UML读书小感

这3天在看谭云杰的thinking in UML这本书,500多页的PDF扫描版,现在只看到279页,算是看完了一半,很多概念都是半懂不懂的,如在云山雾罩中一样。虽然看得不太明白,但是也有一些小感悟。

  1. 代码并不是全部,前期的需求分析,建模设计才是重点,这个就像行军打仗做好作战方略,备好粮草一样,后面的代码就是排兵步阵了。
  2. UML能看懂,不代表会画,会画的人必定是懂得RUP的人,这也解释了我这个初学者连一个小小的多用户登录FTP的程序的用例图都没画好的原因。
  3. 目标问题,我的目标是学会python,先掌握一门语言,而不是先上来就更高级的系统分析,有点好高骛远了。
  4. 不过,这本书看到,然后现在停下来,还是对我有不小的收获,对于整个软件开发的全貌有了不同的认识。同时也理解为什么很多公司不愿意招培训班或者自学的人了,因为如果只会写代码,像一些沟通用图如UML没有掌握,团队之间就不好沟通。

2. FTP作业重写

2.1 软件目录结构

按照老师的讲解,在命令行模式下输入python FTPServer.py start.

另一个命令行输入python FTPClient.py -s 127.0.0.1 -p 9999

2.2 FTPClient端脚本

2.2.1 bin目录下的FTPClient.py模块

import os
import sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from lib import client if __name__ == '__main__': client.Client(sys.argv)

2.2.2 config目录下的settings.py模块

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
USER_HOME = os.path.join(BASE_DIR, "db", "users")

2.2.3 lib目录下的client.py模块

import os
import sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import hashlib
import json
import socket
from config import settings
import getpass
import time class Client(object):
def __init__(self, sys_argv):
self.USER_HOME = settings.USER_HOME
self.cwd = ""
self.args = sys_argv
self.HOST_IP = None
self.HOST_PORT = None
self.sock = None
self.logout_flag = False
self.response_code_dict = {
"100": "user successfully registerd",
"101": "username already existed,enter another username",
"200": "pass users authentication",
"201": "wrong username or password",
"202": "user does not exist",
"300": "ready to get file from server",
"301": "ready to send to server",
"302": "file doesn't exist on ftp server",
"303": "storage is full",
"601": "changed directory",
"602": "failed to find directory",
"2003": "already existed",
"2004": 'continue put',
"2005": "directory created"
}
self.argv_parse() def argv_parse(self):
if len(self.args) < 5:
self.help_msg()
sys.exit()
else:
mandatory_fields = ['-s', '-p']
for i in mandatory_fields:
if i not in self.args:
self.help_msg()
sys.exit()
try:
self.HOST_IP = self.args[self.args.index('-s') + 1]
self.HOST_PORT = int(self.args[self.args.index('-p') + 1])
self.handle()
except (IndexError, ValueError):
# 如果有索引错误,就打印帮助信息并退出程序
self.help_msg()
sys.exit("hhhh") def help_msg(self):
msg = """
input like below:\n
python FTPClient.py -s 127.0.0.1 -p 9999
"""
print(msg) def handle(self):
self.connect(self.HOST_IP, self.HOST_PORT)
while True:
username = input("username:>>>").strip()
password = getpass.getpass("password:>>>").strip()
md5 = hashlib.md5("lan".encode("utf-8"))
md5.update(password.encode("utf-8"))
password = md5.hexdigest()
user_pwd_dict = {"username": username, "password": password}
user_pwd = json.dumps(user_pwd_dict)
inp = input("请输入数字:1是登录,2是注册(q退出):>>>").strip()
if len(inp) < 1:
continue
if inp == '1':
if self.auth(user_pwd):
self.interactive()
elif inp == '2':
self.register(user_pwd)
elif inp.lower() == 'q':
break
else:
print("Invalid input")
self.sock.close() def connect(self, ip, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((ip, port,)) def auth(self, user_pwd):
'''
验证用户名与密码
:param user_pwd:
:return:
'''
self.sock.sendall(("user_auth|%s" % user_pwd).encode("utf-8"))
data = json.loads(self.sock.recv(1024).decode("utf-8"))
if data["result"] == "200":
self.username = data["username"]
self.cwd = data["user_home"]
self.storage_limit = data["storage_limit"]
self.storage_used = data["storage_used"]
return True
elif data["result"] == "202":
print(self.response_code_dict["202"])
return False
else:
print(self.response_code_dict["201"])
return False def register(self, user_pwd):
'''
注册用户
:param user_pwd:
:return:
'''
self.sock.sendall(("user_register|%s" % user_pwd).encode("utf-8"))
msg = self.sock.recv(1024)
if msg == b"100":
print(self.response_code_dict["100"])
elif msg == b"101":
print(self.response_code_dict["101"]) def interactive(self):
while not self.logout_flag:
cmd = input("[%s %s]:" % (self.username, self.cwd)).strip()
if len(cmd) < 1: continue
cmd_str = "cmd_" + cmd.split()[0] if hasattr(self, cmd_str):
func = getattr(self, cmd_str)
func(cmd)
else:
print("Invalid command") def cmd_cd(self, cmd):
'''
切换路径
:param cmd:
:return:
'''
if len(cmd.split()) < 2: pass
input_path = cmd.split()[1].strip()
print("try_path:>>>", input_path)
dir_list = self.cwd.split(os.sep)
print("dir_list:>>>", dir_list) # ["lanxing",""]
if dir_list[-1] == "":
del dir_list[-1]
new_path = ""
if input_path == "..":
del dir_list[-1] # []
if len(dir_list) > 0:
new_path = os.sep.join(dir_list) + os.sep
else:
if input_path.startswith(self.cwd):
new_path = input_path
else:
new_path = os.path.join(self.cwd, input_path) + os.sep
print("new_path:>>>", new_path)
if not new_path.startswith(self.username):
pass
else:
data = {"cwd": new_path}
data_json = json.dumps(data)
self.sock.sendall(("cd|%s" % data_json).encode("utf-8"))
server_reply = self.sock.recv(1024)
auth_result = json.loads(server_reply.decode("utf-8"))
if auth_result["result"] == "601":
self.cwd = new_path
else:
print(self.response_code_dict["602"]) def cmd_ls(self, cmd):
msg = ""
if len(cmd.split()) == 1:
msg = json.dumps({"cwd": self.cwd}) elif len(cmd.split()) == 2:
path = cmd.split()[1]
dir_list = self.cwd.split()
new_path = ""
if dir_list[-1] == "":
del dir_list[-1]
if path == "..":
del dir_list[-1]
if len(dir_list) > 0:
new_path = os.sep.join(dir_list) + os.sep
else:
if path.startswith(self.user_def_cwd):
new_path = path
else:
new_path = self.user_def_cwd + path if not new_path.startswith(self.user_def_cwd):
pass
msg = json.dumps({"cwd": new_path})
self.sock.sendall(("ls|{0}".format(msg)).encode("utf-8"))
msg_size = int(self.sock.recv(1024).decode("utf-8"))
self.sock.sendall(b"300")
has_received = 0
auth_result = ""
while has_received < msg_size:
data = self.sock.recv(1024)
auth_result += data.decode("utf-8")
has_received += len(data)
auth_result = json.loads(auth_result)
if auth_result["result"]:
print(auth_result["result"])
else:
print(self.response_code_dict["302"]) def cmd_put(self, cmd):
data = {"file_size": None, "file_name": None, "dst_path": None} if len(cmd.split()) == 2:
src_file = cmd.split()[1]
dst_path = self.cwd
else:
src_file, dst_path = cmd.split()[1], cmd.split()[2]
if len(src_file.split(os.sep)) == 1:
src_file = os.path.join(settings.BASE_DIR, "bin", src_file)
if os.path.isfile(src_file):
file_size = os.stat(src_file).st_size
data["file_size"] = file_size
data["file_name"] = os.path.basename(src_file)
if dst_path.startswith("lanxing"):
data["dst_path"] = dst_path
else:
print("Wrong directory!")
data_json = json.dumps(data)
self.sock.sendall(("put|%s" % data_json).encode("utf-8"))
auth_result = json.loads(self.sock.recv(1024).decode("utf-8"))
print(auth_result)
has_sent = 0
with open(src_file, "rb") as f:
if auth_result["result"] == "2003":
print(self.response_code_dict["2003"], )
print("服务端同名文件大小:%s,本地文件大小:%s" % (auth_result["file_size"], file_size))
choice = input("Y:续传;N:覆盖 >>>").strip()
if choice.upper() == "Y":
f.seek(auth_result["file_size"])
self.sock.sendall(b"2004")
has_sent += auth_result["file_size"]
elif choice.upper() == "N":
self.sock.sendall(b"301")
elif auth_result["result"] == "302":
self.sock.sendall(b"301")
print(self.sock.recv(1024))
for line in f:
self.sock.sendall(line)
has_sent += len(line)
percent = has_sent / file_size * 100
sys.stdout.write("\r")
sys.stdout.write("%.2f%% |%s" % (percent, int(percent) * "*"))
sys.stdout.flush()
time.sleep(0.01) else:
print("file does not exist!") def cmd_get(self, cmd):
client_path = ""
data = {
"file_name": None,
"client_path": None,
"file_size": None,
"result":"300"
}
if len(cmd.split()) > 1:
file_path = cmd.split()[1]
file_name = os.path.basename(file_path)
if file_path.startswith(self.username):
client_path = file_path
else:
client_path = os.path.join(self.cwd, file_path)
if len(cmd.split()) == 2:
dst_path = os.path.join(settings.USER_HOME, self.cwd, file_name)
elif len(cmd.split()) == 3:
dst_path = cmd.split()[2]
if not dst_path.startswith(self.username):
dst_path = os.path.join(settings.USER_HOME, self.cwd, dst_path, file_name)
else:
dst_path = os.path.join(settings.USER_HOME, dst_path, file_name)
if os.path.exists(dst_path):
file_size = os.stat(dst_path).st_size
data["file_size"] = file_size
data["client_path"] = client_path
data_json = json.dumps(data)
self.sock.sendall(("get|%s" % data_json).encode("utf-8"))
server_reply = json.loads(self.sock.recv(1024).decode("utf-8"))
has_received = 0
if server_reply["result"]=="2003":
choice=input("目标文件已存在,续载Y或全部重新下载N:").strip()
if choice.upper() =="Y":
data["result"]="2004"
data_json = json.dumps(data).encode("utf-8")
self.sock.sendall(data_json)
has_received += file_size
try:
os.makedirs(os.path.dirname(dst_path))
except OSError:
pass
with open(dst_path,"ab") as f:
while has_received < server_reply["file_size"]:
ret = self.sock.recv(1024)
f.write(ret)
has_received += len(ret)
percent = has_received/server_reply["file_size"]*100
sys.stdout.write("\r")
sys.stdout.write("%.2f%%"%percent)
sys.stdout.flush()
elif choice.upper()=="N":
data["result"] = "300"
data_json = json.dumps(data).encode("utf-8")
self.sock.sendall(data_json)
try:
os.makedirs(os.path.dirname(dst_path))
except OSError:
pass
with open(dst_path, "wb") as f:
while has_received < server_reply["file_size"]:
ret = self.sock.recv(1024)
f.write(ret)
has_received += len(ret)
percent = has_received / server_reply["file_size"] * 100
sys.stdout.write("\r")
sys.stdout.write("%.2f%%" % percent)
sys.stdout.flush()
elif server_reply["result"]=="300":
data["result"] = "300"
data_json = json.dumps(data).encode("utf-8")
self.sock.sendall(data_json)
try:
os.makedirs(os.path.dirname(dst_path))
except OSError:
pass
with open(dst_path, "wb") as f:
while has_received < server_reply["file_size"]:
ret = self.sock.recv(1024)
f.write(ret)
has_received += len(ret)
percent = has_received / server_reply["file_size"] * 100
sys.stdout.write("\r")
sys.stdout.write("%.2f%%" % percent)
sys.stdout.flush() else:
print("Wrong instructions") def cmd_mkdir(self, cmd):
new_path = ""
if len(cmd.split()) <= 1:
pass
elif len(cmd.split()) == 2:
input_path = cmd.split()[1] if input_path.startswith(self.cwd):
new_path = input_path
else:
new_path = os.path.join(self.cwd, input_path)
print("new_path>>>", new_path)
msg = json.dumps({"cwd": new_path})
self.sock.sendall(("makedirs|{0}".format(msg)).encode("utf-8"))
auth_result = json.loads(self.sock.recv(1024).decode("utf-8"))
if auth_result["result"] == "2003":
print(self.response_code_dict["2003"])
else:
print(self.response_code_dict["2005"]) def cmd_exit(self, cmd):
self.logout_flag = True

2.3 FTPServer端脚本

2.3.1 bin目录下的FTPServer.py模块

import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from lib import main if __name__ == '__main__':
main.ArgvHandler(sys.argv)

2.3.2 config目录下的settings.py模块

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
USER_HOME = os.path.join(BASE_DIR, "db", "users")
HOST_IP = "127.0.0.1"
HOST_PORT = 9999
USER_ACCOUNT_DIR = os.path.join(BASE_DIR, "db", "user_account")

2.3.3 lib目录下的main.py模块与ftp_server.py模块

main.py模块

import os, sys

sys.path.append(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import socketserver
import ftp_server
from config import settings class ArgvHandler(object):
def __init__(self, sys_argv):
self.args = sys_argv
self.argv_handle() def argv_handle(self):
'''
处理命令行参数,看是否符合输入规范
:return:
'''
if len(self.args) < 2:
self.help_msg()
else:
first_argv = self.args[1] # first_argv = "start"
if hasattr(self, first_argv):
# 通过反射判断现有类的对象是否有start方法
func = getattr(self, first_argv)
# 有则通过反射拿到此方法,并运行此方法
func()
else:
self.help_msg() def help_msg(self):
msg = """
input like below:\n
python FTPServer start
""" def start(self):
"""
创建多线程socket对象,并让该对象一直运行
:return:
"""
try:
print("starting")
tcp_server = socketserver.ThreadingTCPServer((settings.HOST_IP, settings.HOST_PORT,),ftp_server.MyServer)
print("server started")
tcp_server.serve_forever()
except KeyboardInterrupt:
pass

ftp_server.py模块

import os
import sys sys.path.append(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import subprocess
import json
import socketserver
from config import settings class MyServer(socketserver.BaseRequestHandler):
response_code_dict = {
'100': 'user successfully registered',
'101': 'username already existed',
'200': 'Pass authentication!',
'201': 'Wrong username or password!',
'202': 'user does not exist',
'300': 'Ready to send file to client',
'301': 'Client ready to receive file',
'302': "File doesn't exist",
'2002': 'ACK(可以开始上传)',
'2003': 'already existed',
'2004': 'continue put',
"2005": "directory created"
} def handle(self):
while True:
# 死循环,一直接收客户端发过来的消息
data = self.request.recv(1024).decode()
if not data:
# 如果用户发过来的消息是空,则判定用户断开连接
break
data = data.split("|")
func_str = data[0] # 通过反射查看对象有无此属性
if hasattr(self, func_str):
func = getattr(self, func_str)
func(json.loads(data[1]))
else:
print("Invalid instructions") def user_auth(self, name_pwd):
username = name_pwd["username"]
password = name_pwd["password"]
auth_result = {
"username": username,
"password": password,
"storage_size": 0,
"storage_used": 0,
"result": "201",
"user_home": ""
}
with open(settings.USER_ACCOUNT_DIR, "r", encoding="utf-8") as f:
user_info = json.load(f)
if username in user_info.keys():
if password == user_info[username]["password"]:
self.login_user = username
path = os.path.join(settings.USER_HOME, username)
try:
os.makedirs(path)
except OSError:
pass
self.login_user_home = os.path.join(self.login_user) + os.sep
auth_result["user_home"] = self.login_user_home
auth_result["result"] = "200"
auth_result["storage_limit"] = user_info[username]["storage_limit"]
auth_result["storage_used"] = self.getdirsize(path)
else:
auth_result["result"] = "202"
data = json.dumps(auth_result).encode("utf-8")
self.request.sendall(data) def user_register(self, name_pwd):
with open(settings.USER_ACCOUNT_DIR, "r", encoding="utf-8") as f:
user_info = json.load(f)
if name_pwd["username"] in user_info:
self.request.sendall(b"101")
else:
name_pwd["storage_limit"] = 104857600
user_info[name_pwd["username"]] = name_pwd
self.request.sendall(b"100")
with open(settings.USER_ACCOUNT_DIR, "w", encoding="utf-8") as f:
json.dump(user_info, f) def cd(self, dir_str):
new_path = dir_str["cwd"]
# print(new_path)
server_path = settings.USER_HOME + os.sep + new_path
# print(server_path)
auth_result = {"result": "602"}
if os.path.exists(server_path):
auth_result["result"] = "601"
auth_result_json = json.dumps(auth_result)
self.request.sendall(auth_result_json.encode("utf-8")) def ls(self, ins):
dir_str = ins["cwd"]
server_path = os.sep.join([settings.USER_HOME, dir_str])
auth_result = {"result": None}
if os.path.exists(server_path):
path = os.path.join(settings.USER_HOME, server_path)
if sys.platform == "win32":
command = "dir" + " " + path
else:
command = "ls" + " " + path
auth_result["result"] = subprocess.getoutput(command)
msg_size=len(json.dumps(auth_result).encode("utf-8"))
self.request.sendall(str(msg_size).encode("utf-8"))
self.request.recv(1024)
self.request.sendall(json.dumps(auth_result).encode("utf-8")) def put(self, data):
file_size = data["file_size"]
file_name = data["file_name"]
dst_path = data["dst_path"]
file_path = os.path.join(settings.USER_HOME, dst_path, file_name)
# print(file_path)
if os.path.exists(file_path):
file_size2 = os.stat(file_path).st_size
if file_size2 <=file_size:
data["file_size"] = file_size2
data["result"] = "2003" else:
data["result"] = "302"
print(data)
data_json = json.dumps(data)
self.request.sendall(data_json.encode("utf-8"))
client_msg = self.request.recv(1024).decode("utf-8")
has_received = 0
if client_msg == "2004":
has_received += file_size2
with open(file_path, "ab") as f:
self.request.sendall(b"2002")
while has_received < file_size:
data1 = self.request.recv(1024)
f.write(data1)
has_received += len(data1) elif client_msg =="301":
try:
os.makedirs(os.path.dirname(file_path))
except OSError:
pass
with open(file_path, "wb") as f:
self.request.sendall(b"2002")
while has_received < file_size:
data1 = self.request.recv(1024)
f.write(data1)
has_received += len(data1) def get(self, data):
client_path = data["client_path"]
print("client_path>>>",client_path)
file_size = data["file_size"]
data["result"]="2003"
server_path = os.path.join(settings.USER_HOME,client_path)
if os.path.isfile(server_path):
file_size2 = os.stat(server_path).st_size
if not file_size:
data["result"]="300"
data["file_size"] = file_size2
data_json = json.dumps(data).encode("utf-8")
self.request.sendall(data_json)
client_reply = json.loads(self.request.recv(1024).decode("utf-8"))
with open(server_path,"rb") as f :
if client_reply["result"] == "2004":
f.seek(file_size)
for line in f:
self.request.sendall(line) def getdirsize(self, path):
file_size = 0
for root, dirs, files in os.walk(path):
file_size += sum([os.path.getsize(os.path.join(root, name)) for name in files])
return file_size def makedirs(self, data):
path = data["cwd"]
server_path = os.path.join(settings.USER_HOME, path)
print(server_path)
auth_result = {"result": None}
if os.path.exists(server_path):
auth_result["result"] = "2003"
else:
os.makedirs(server_path)
auth_result["result"] = "2005"
msg = json.dumps(auth_result).encode("utf-8")
self.request.sendall(msg)

python day 18: thinking in UML与FTP作业重写的更多相关文章

  1. 十八. Python基础(18)常用模块

    十八. Python基础(18)常用模块 1 ● 常用模块及其用途 collections模块: 一些扩展的数据类型→Counter, deque, defaultdict, namedtuple, ...

  2. python之ftp作业【还未完成】

    作业要求 0.实现用户登陆 1.实现上传和下载 3.每个用户都有自己的家目录,且只可以访问自己的家目录 4.对用户进行磁盘配额,每个用户的空间不同,超过配额不允许下载和上传 5.允许用户在指定的家目录 ...

  3. Python学习笔记——基础篇【第七周】———FTP作业(面向对象编程进阶 & Socket编程基础)

    FTP作业 本节内容: 面向对象高级语法部分 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 参考:http://www.cnblogs.com/wupeiqi/ ...

  4. python day33 ,socketserver多线程传输,ftp作业

    一.一个服务端连多个客户端的方法 1.服务端 import socketserver class MyServer(socketserver.BaseRequestHandler): def hand ...

  5. python全栈开发day29-网络编程之socket常见方法,socketserver模块,ftp作业

    一.昨日内容回顾 1.arp协议含义 2.子网,子网掩码 3.两台电脑在网络中怎么通信的? 4.tcp和udp socket编码 5.tcp和udp协议的区别 6.tcp三次握手和四次挥手,syn洪攻 ...

  6. Python window console 控制台 实现最后一行输出 print 重写

    Python window console 控制台 实现最后一行输出 print 重写 # -*- coding: utf-8-*- from __future__ import print_func ...

  7. python 开发一个支持多用户在线的FTP

    ### 作者介绍:* author:lzl### 博客地址:* http://www.cnblogs.com/lianzhilei/p/5813986.html### 功能实现 作业:开发一个支持多用 ...

  8. python基础——18(面向对象2+异常处理)

    一.组合 自定义类的对象作为另一个类的属性. class Teacher: def __init__(self,name,age): self.name = name self.age = age t ...

  9. Python实现支持并发、断点续传的FTP

    参考网上一个FTP程序,重写了一遍,并稍加扩展 一.要求 1. 支持多用户同时登录 2. 可以注册用户,密码使用md5加密 3. 可以登录已注册用户 4.  支持cd切换目录,ls查看目录子文件 5. ...

随机推荐

  1. C-Store: A Column-oriented DBMS Mike

    这篇paper比较老,是列存比较基础的论文 几乎所有列存,或olap的论文都会引用这篇 行存面向写,支持OLTP 列存面向读,支持OLAP 基于磁盘的DBMS,瓶颈基本在磁盘IO,所有做的工作都是用多 ...

  2. PHP MQTT 实践

    MQTT介绍:http://mqtt.org 服务器端https://mosquitto.org/download/ PHP客户端https://github.com/bluerhinos/phpMQ ...

  3. Flutter的Padding、Raw、Column、Expanded组件的基本使用

    Padding组件: Padding组件的基本使用代码: import 'package:flutter/material.dart'; import 'package:flutter_testdem ...

  4. Centos7安装完成后设定基本的网络配置

    Centos7设定网络 新安装的centos7,网络默认是不启动的,需要人为的手工修改配置文件,在这里把这个过程简要的记录一下. 设定ip地址与mac地址自定义 [root@web ~]# cd /e ...

  5. GenTree:基因进化和功能分析

    欢迎来到"bio生物信息"的世界 GenTree是一个集合多种数据的在线数据库. 总共涉及的基因有63152个,蛋白质编码基因有20300个. 评估基因年龄用的是UCSC数据库的1 ...

  6. EasyDSS高性能流媒体服务器开发RTMP直播同步输出HLS(m3u8)录像功能实现时移回放的方案

    EasyDSS商用流媒体服务器解决方案是由EasyDarwin开源团队原班人马开发的一套集流媒体点播.转码与管理.直播.录像.检索.时移回看于一体的一套完整的商用流媒体服务器解决方案,支持RTMP推流 ...

  7. Mac Pro 2015休眠掉电解决办法

    硬件:Mac Pro 2015 系统:MacOs Mojave 10.14.3 问题:合盖的时候,休眠1小时掉电10%,由于之前是128G原装盘不会有这个问题,后面购买了M.2转接卡,更换1T Int ...

  8. Spring Boot 的Logback

    Spring Boot 默认使用Logback记录日志 Spring Boot starter 都会默认引入spring-boot-starter-logging,不需要再引入 日志级别从高到低:TR ...

  9. csu 1976: 搬运工小明

    1976: 搬运工小明 Submit Page   Summary   Time Limit: 2 Sec     Memory Limit: 128 Mb     Submitted: 94     ...

  10. XGBoost中参数调整的完整指南(包含Python中的代码)

    (搬运)XGBoost中参数调整的完整指南(包含Python中的代码) AARSHAY JAIN, 2016年3月1日     介绍 如果事情不适合预测建模,请使用XGboost.XGBoost算法已 ...