月度归档: 2021 年 4 月

python相机标定

python相机标定
采用的是张正友方法,参考以下文章:https://github.com/Nocami/PythonComputerVision-6-CameraCalibration
在该方法的基础上实现了批量的定标,便于软件设计。

# -*- coding: utf-8 -*-
from cv2 import cv2
import numpy as np
import glob
class Cphoto_pre_work:

def __init__(self):
self.obj_points = [] # 存储3D点
self.img_points = [] # 存储2D点
self.size=[]
self.ret=[]
self.mtx=[]
self.dist=[]
self.rvecs=[]
self.tvecs=[]
self.list1=[‘ret’,’mtx’,’dist’,’rvecs’,’tvecs’]
self.savesrc5=[]

def get_grid(self,src,src_corner):
#进行标定
#src:图像路径
#src_corner:棋盘格坐标路径
images = glob.glob(src)
# 设置寻找亚像素角点的参数,采用的停止准则是*大循环次数30和*大误差容限0.001
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 获取标定板角点的位置
objp = np.zeros((4*6,3), np.float32)
objp[:,:2] = np.mgrid[0:6,0:4].T.reshape(-1,2) # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y
i=0
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
self.size = gray.shape[::-1]
ret, corners = cv2.findChessboardCorners(gray, (6, 4), None)

if ret:
self.obj_points.append(objp)
corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), criteria) # 在原角点的基础上寻找亚像素角点

if [corners2]:
self.img_points.append(corners2)
else:
self.img_points.append(corners)
i+=1
cv2.drawChessboardCorners(img, (6, 4), corners, ret) # 记住,OpenCV的绘制函数一般无返回值
cv2.imwrite(src_corner+fname.rsplit(“\\”,1)[1],img)
# cv2.imwrite(‘./outimg/conimg’+str(i)+’.jpg’, img)
# cv2.waitKey(4000)
if self.img_points:
return True
else:
return False

def get_parameter5(self,savesrc):
# 保存相应5个标定参数,并存储
self.savesrc5=savesrc
self.ret, self.mtx, self.dist, self.rvecs, self.tvecs = cv2.calibrateCamera(self.obj_points, self.img_points,self.size, None, None)
np.save(savesrc+ self.list1[0],self.ret)
np.save(savesrc+ self.list1[1],self.mtx)
np.save(savesrc+ self.list1[2],self.dist)
np.save(savesrc+ self.list1[3],self.rvecs)
np.save(savesrc+ self.list1[4],self.tvecs)
def last_photo(self,imgsrc,src_par5,last_src):
#imgsrc:原始影像路径
#src_part5:5参数路径
#last_src:*后保存路径
#选择指定文件夹即可直接读入文件夹内保存的.npy数据,生成相片
origin_images = glob.glob(imgsrc+’\*.[jp][pn]g’)
for tempfname in origin_images:
tempimg=cv2.imread(tempfname)
h,w=tempimg.shape[:2]
# print(tempfname.rsplit(“\\”,1)[1])
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(np.load(src_par5+self.list1[1]+’.npy’),np.load(src_par5+self.list1[2]+’.npy’),(w,h),1,(w,h))#显示更大范围的图片(正常重映射之后会删掉一部分图像)
print (newcameramtx)
print(“——————使用undistort函数——————-“)
temp_dst=cv2.undistort(tempimg,np.load(src_par5+self.list1[1]+’.npy’),np.load(src_par5+ self.list1[2]+’.npy’),None,newcameramtx)
x,y,w,h = roi
tempdst1 = temp_dst[y:y+h,x:x+w]
cv2.imwrite(last_src+tempfname.rsplit(“\\”,1)[1], tempdst1)
print (“方法一:dst的大小为:”, tempdst1.shape)

if __name__ == ‘__main__’:
temp=Cphoto_pre_work()
temp.get_grid(‘.\images4\*.jpg’,’./savecorner’+’/’)
srccc=r’E:\canshu’+’\\’
temp.get_parameter5(srccc)
temp.last_photo(‘.\images4′,srccc,’./saveimg’+’/’)

nump使用

nump使用

import numpy as np

arr1 = np.array([1, 2, 3, 4])
print(arr1)
arr2 = np.array([[1, 2, 3, 1], [4, 5, 6, 3], [4, 8, 9, 10]])
print(arr2)
np_linspace = np.linspace(0, 1, 12)
print(np_linspace)

#矩阵的生成
np_zeros = np.zeros((2, 3))
print(np_zeros)
np_eye = np.eye(3)
print(np_eye)
np_diag = np.diag([1, 2, 3, 4])
print(np_diag)

# 数组的属性
print(arr2.shape)
print(arr2.ndim)
print(arr2.size)
print(arr2.dtype)
print(arr2.itemsize)

#类型转换
print(np.float(32))
print(np.int8(34))
print(bool(0))
print(np.float(True))
print(np.float(False))

#数组下标查找
print(arr2[2][:2])
print(arr2[0, 0:3])

#数组形状
arr2.shape = 4, 3
print(arr2)
print(arr1.reshape(2,2))
arr_1 = np.arange(24).reshape(4,6)
print(arr_1)
print(arr_1.ravel())
print(arr_1.flatten()) # 横向
print(arr_1.flatten(‘F’)) # 纵向

#改变数组
arr3 = np.array([5,6,7,8])
print(np.hstack((arr1,arr3)))
print(np.vstack((arr1,arr3)))
print(np.concatenate((arr1,arr3),axis=0))

#数组切割
print(np.hsplit(arr3,2))
print(np.vsplit(arr2,2))
print(np.split(arr2,2,axis=0))

#随机生成数字
print(np.random.random(100))
print(np.random.rand(10,5))
print(np.random.randn(10,5))
print(np.random.randint(2,10,size=[2,5]))

#矩阵生成与运算
maty1 = np.mat(‘1,2,3;4,5,6;7,8,9’)
print(maty1)
maty2 = np.matrix([[1,2,3],[4,5,6],[7,8,9]])
print(maty2)
print(maty2*3)
print(maty2+maty1)
print(maty2*maty1)
print(np.dot(maty2,maty1))
print(maty1.T)
print(maty1.H)
print(maty1.I)

 

python群发邮件

python群发邮件

1. 前言
1.1 应朋友要求,写一个群发邮件的脚本,用来实现往每个人的邮箱里边发送自己的工资条

2. 数据格式,*后一列是邮箱地址%title插图%num

3. 脚本实现的功能
3.1 自定义邮件标题

3.2 记录发送成功或失败的个数,防止发送失败

4. 代码实现

# -*- coding: utf-8 -*-
# @Time : 2021/3/26 10:11
# @Author : liyf–95/02/02
# @File : send_email.py
# @Software: PyCharm

import xlrd
import time
import re
from email.mime.text import MIMEText
from smtplib import SMTP_SSL

from loguru import logger

# qq邮箱smtp服务器
host_server = ‘smtp.qq.com’
# sender_qq为发件人的qq号码
sender_qq = ‘123456@qq.com’
# 第三方客户端登录时需要的授权码,不是qq密码
pwd = ‘xxxxxxxxxxxxx’
# 发件人的邮箱
sender_qq_mail = ‘123456@qq.com’
# 获取当前月份
batch = time.strftime(“%Y-%m”, time.localtime())

suffix = time.strftime(“%Y%m”, time.localtime())

def get_success_error_counts():
“””
用来读取日志文件中的数据,并转成列表形式,方便调用该函数处理列表中的数据,用来做去重处理
:return: 列表
“””
success_email_list = []

try:
with open(f’success_log_{suffix}.txt’, ‘r’, encoding=’utf8′) as f:
results = f.readlines()
for res in results:
success_email_list.append(res.strip())
except Exception:
logger.error(f’success_log_{suffix}.txt 文件不存在,初始化列表为0!’)
success_email_list = success_email_list

error_list = []
try:
with open(f’error_log_{suffix}.txt’, ‘r’, encoding=’utf8′) as f:
results = f.readlines()
for res in results:
restr = res.strip()
email = re.findall(re.compile(r”email’: ‘(.*?)’, ‘”, re.S), restr)[0]
error_list.append(email)
except Exception:
error_list = error_list

return success_email_list, error_list

def read_excel(subject):
“””
读取excel数据
:param subject: 自定义的邮件标题
:return:
“””
workbook = xlrd.open_workbook(‘工资条2.xlsx’)

worksheet = workbook.sheet_by_index(0)

nrows = worksheet.nrows
# 定义一个空列表,用来存放每一个员工的数据,包括表头
total_list = []
for i in range(nrows):
data_list = worksheet.row_values(i)
if data_list[0] == ”:
pass
else:
total_list.append(data_list)
logger.info(f’数据读取完毕,共有 {len(total_list) – 1} 位同事’)
logger.info(‘————————————————————‘)
time.sleep(2)
for k, v in enumerate(total_list[1:]):
msg_content = ”
for i, j in enumerate(v):
if total_list[0][i] == ‘邮箱’:
pass
else:
# 有一些列的数据为空,处理数据
val = ‘无’ if str(v[i]).strip() == ” else v[i]
msg = f’# {total_list[0][i]}:{val}\n’
msg_content += msg
name = v[0]
email_addr = v[-1]
success, error = get_success_error_counts()
logger.info(f’正在向第 {k + 1}/{len(total_list) – 1} 位同事 {name} 发送邮件,请稍等…’)
if len(success) == 0:
# 说明日志中没有数据,即还没有发送成功的例子
# 开始发送数据
email_content = f’尊敬的 {name} 同事,您好,您的 {batch} 月份工资单信息如下:\n{msg_content}# 发送时间:{time.strftime(“%Y-%m-%d %H:%M:%S”, time.localtime())}’
send_email_to_member(email_addr, email_content, name, subject)
logger.info(f’已发送至邮箱:{email_addr},接收人:{name}’)
else:
# 已经有发送成功的例子,并已存入success_log.txt文件中
email_list = [] # 用来存放success_log.txt文件中的邮箱地址,用来去重
for data in success:
email_list.append(str(data).split(‘—->’)[-1])
if email_addr in email_list:
# 如果需要发送邮件的邮箱地址在success_log.txt文件中,则说明该邮箱已经发送过,无需重复发送
logger.warning(f'{name} 同事:{email_addr} 已经发送过了,无需重复发送邮件!!’)
pass
else:
# 正常发送邮件
email_content = f’尊敬的 {name} 同事,你好,您的 {batch} 月份工资单信息如下:\n{msg_content}# 发送时间:{time.strftime(“%Y-%m-%d %H:%M:%S”, time.localtime())}’
send_email_to_member(email_addr, email_content, name, subject)
logger.info(f’已发送至邮箱:{email_addr},接收人:{name}’)
logger.info(‘————————————————————‘)
logger.info(f’脚本运行结束!等待5分钟后自动关闭窗口(或者手动点击窗口右上角关闭)!!!’)
logger.info(‘运行结果:’)
logger.info(f'{len(total_list) – 1} 位同事已全部发送完毕’)
success, error = get_success_error_counts()
logger.info(f’Successd:{len(success)},Failed:{len(error)}’)
time.sleep(300)

def send_email_to_member(email_addr, email_content, name, subject):
“””
发送邮件
:param email_addr: 收件人邮箱地址
:param email_content: 需要发送的正文内容
:param name: 收件人姓名
:return:
“””
# ssl登录
smtp = SMTP_SSL(host_server)
# set_debuglevel()是用来调试的。参数值为1表示开启调试模式,参数值为0关闭调试模式,
smtp.set_debuglevel(0)
smtp.ehlo(host_server)
smtp.login(sender_qq, pwd)

msg = MIMEText(email_content, “plain”, ‘utf-8′)
msg[“Subject”] = subject # 邮件标题
msg[“From”] = sender_qq_mail # 发件人
msg[“To”] = email_addr # 收件人邮箱
try:
smtp.sendmail(sender_qq_mail, email_addr, msg.as_string())
smtp.quit()
msg = f'{name} 发送成功,时间: {time.strftime(“%Y-%m-%d %H:%M:%S”, time.localtime())}—->{email_addr}’
with open(f’success_log_{suffix}.txt’, ‘a’, encoding=’utf8′) as f:
f.write(msg)
f.write(‘\n’)
f.close()
time.sleep(0.5)
except Exception as e:
logger.error(f’发送失败—>{name}\n原因:{e}’)
item = {}
item[‘name’] = name
item[’email’] = email_addr
item[‘error_reason’] = e
item[‘date’] = time.strftime(“%Y-%m-%d %H:%M:%S”, time.localtime())
with open(f’error_log_{suffix}.txt’, ‘a’, encoding=’utf8′) as f:
f.write(str(item))
f.write(‘\n’)
f.close()

if __name__ == ‘__main__’:
subject = input(‘请输入自定义邮件标题:’)
logger.info(f’自定义邮件标题为:{subject}’)
read_excel(subject)
5. 逻辑梳理
5.1 该脚本的使用qq邮箱发送,其中获取授权码可以 点击这里参考博客

5.2 注意事项

5.2.1 excel名称必须为 `工资条2.xlsx`

5.2.2 `邮箱` 列必须为*后一列,`姓名` 列必须在*列,因为代码中 `name=v[0], email_addr=v[-1]` 是固定的。可以自己做适当修改

5.2.3 表头名称可以随意改动,列数也可以随意增减,但要保证 `邮箱` 和 `姓名` 列存在

6. success_log_202103.txt 和 error_log_202103.txt 的作用
6.1 success_log_202103.txt

6.1.1 用来记录发送成功的数据

6.1.2 发送邮件之前,会先读取该txt文件,并判断要发送的email地址是否在txt里边,如果存在,则不发送,防止重复发送

6.2 error_log_202103.txt

6.2.1 一般情况下,没有这个文件,但是由于一些不可控因素,比如邮箱地址不存在或者断网等,会导致发送邮件失败

6.2.2 发送失败之后会把当前发送的数据记录下来,就会生成这个文件

6.2.3 如果该文件有数据,则首先检查是否是邮箱不正确导致的,如果不是,重新运行exe文件

7. 测试
7.1 使用 `pyinstaller -F send_email.py` 打包 py 文件为 exe 可执行文件

7.2 运行截图

%title插图%num

7.3 邮件内容

%title插图%num

技术人的灵魂 3 问,阿里工程师如何解答?

%title插图%num

**导读:**在业务团队做事的工程师摸爬滚打了一段时间后,一定会有所疑问。团队同学在*初的一段时间都提出这样的疑惑:如何在业务中发现有技术价值的问题?发现问题后如何思考和发起再到解决?*后的技术结果跟业务结果如何衔接?很多时候我们听别人说“思考是不够的/要多思考”,其实都是在说这几点。接下来,阿里高级前端技术专家氐宿谈一谈遇到这三个问题时,他是如何解决的?

如何在业务中发现有技术价值的问题?
一位科学家一生可用于研究的时间*其有限,然而,世界上的研究主题却多得数不清。如果只因为稍微觉得有趣就选为研究主题,将在还没来得及做真正重要的事时,一生就结束了。
——利根川进

其实要解答这个问题之前,我们要理解一个概念,什么是有价值的问题?议题度高和解答质高的问题我理解就是有价值的问题,比较通俗的理解就是这个问题是否存在,当前要解决这个问题的必要性够不够,问题对应的解决方案可行性高不高。如果要在业务里发现这种问题,首先要理解业务战略、打法和定位。那如何才能把这个前置信息做好,对工程师来说是一个比较大的挑战。

首先工程师其实大多数都是从事一线开发,对业务理解可能仅限于自己在做的事情。很多信息都是别人过滤了五六手之后的信息,得到的可能就是一个任务和为什么做这个任务。相对比之下肯定不如制定战略的人懂得战略背后的意义,信息也是不对等的。所以首先我们要收集信息,然后整理归纳,*后分析问题。

1. 先来说说收集信息
其实有点像信息科学里的情报学。收集信息*好的方式就是参加所处业务老大的 KO 会,各种 KO 会会把战略上的拆解和背后的思考整体梳理之后宣讲传达给 BU 或部门的同学,虽然我们没有亲身参与到脑暴过程,但是也会对背后的思考有一定的理解,切记,一定要记得划重点记笔记。

获取*手信息之后,我们要经过简单梳理开始收集外部信息,整理整体的知识脉络,这里我经常用的就是阿里学习(业务宝库阿里学习,技术宝库 ATA,注:阿里内部两个学习平台),可以获取不少业务相关的分享,当然很多外部渠道也同样可以收集到。比如资料《飞猪“新旅行联盟”赋能商家能讲出什么新故事?》就是外部收集到的,可以得出几个关键词,数字技术赋能旅行行业、我们不是 OTA,这些都要整理到自己收集的信息池里。当然以上我提到的都是信息获取源的一种。具体收集信息的释义可以查一下百科,可以按照百科上的方法论学习一遍,以便找到适合自己的方法。总之这里我们要像产品经理一样去收集这些信息。这里也鼓励跟不同领域不同BU的同学多交流,不限于线下扯淡式的交流和线上问问题的方式(这里建议先看下知乎里这个回答关于学会问问题以及如何进行有效社交。

2. 分析问题
我们通过不同信息源获取到的信息是散落的,如何经过加工融入自己的思考体系呢?首先信息不能是简单的堆叠,我们要通过不同的入口理出头绪。可以使用 MECE 法则进行思考拆解,通过无遗漏无重复地分类来把握整体,列出脑图和逻辑树,*后将逻辑树的信息匹配需求场景,可以尝试通过 C 端和 B 端不同入口去还原需求场景。这中间可以结合一定的方法论(演绎推理和归纳推理),去把问题和挑战细化出来,帮助我们理解 BU 的战略,同时我们也能从自身出发把战略拆解到对应的项目。举例来说去年我个人分析飞猪在整个 C 端面临的主要问题之一还是流量格局过于单一,B 端供应链的成熟度不够导致无法给到商家更实质的体验服务,飞猪的类目交叉不够背后是各垂直业务存在业务隔离。

%title插图%num

发现问题到执行该如何衔接?
拿到这三个问题我们不能马上就开干,我们还要提炼这个问题带来的核心价值。否则很容易就会出现投入了巨大工作之后,*后的技术产出和业务结果衔接不上,所以说思考不要用蛮力,工作不只靠体力。要去看里面跟自己角色相关的工作在什么地方?

以端侧来说,有优势的一点是靠近产品侧靠近用户侧,所以基本展现模式都可以通过产品原型进行抽象,形成体系化。以流量体系建设举例我们要对用户进行分层,比较合理的方式可以用到几个经典模型RFM、AIPL、AARRR及其变种,以便沉淀出承接的技术平台或产品。如流量体系建设我们在思考分层过后,把用户按心智划分之后,又从所属域分为散落在阿里域外的用户和阿里域内的内部用户,从而针对性的设计出两个平台产品。
%title插图%num

1. 见龙在田,利见大人
作为项目发起者,我们要关注每一个环节。所以首先我们要找到对应的业务方去“售卖”我们的思考。要找到目标一致的人一起做事,这里首先需要知道的是你要清楚你的业务方都是谁?他们都负责什么?我的方法比较简单,直接看运营在职能上的划分,要清楚自己对的人负责的方向以及他所负责的 KPI。另外切记,一定要和对口 PD 一起去找,通常来说*直接的合作方是能帮你处理业务和技术衔接的那个人。

上下游的人都找到后,要开始准备 KO,理出需求排出优先级。因为在资源有限的情况下,我们究竟该先做哪些?不重要的要放在后面去做,优先考虑你产品*核心的功能。通常平台产品*优先的是运营使用的功能,所以要跟合作方确认哪些功能他们认为*重要。

2. 站在巨人的肩膀上做创新
阿里巴巴已经非常大了,我们相信每一个想法都会有人想过,所以尽量不要走重复的路踩同一个坑,同理小公司利用开源技术亦是如此。那么在项目开始做的时候,如果是平台,我们需要先拆出核心功能,这个核心功能要去看集团是否已经有人在做了或是有成熟方案,避免重复造轮子,同时也能*快*直接的解决你*紧急核心的问题。这其中*简单直接方法就是搜索 ATA(阿里内部技术论坛)和语雀(内部同学通常有知识记录的习惯),拆关键词找到做事情的关键人。你要相信你*不是*个想到该问题的人,一些通用问题一定在集团内已经有通用的服务提供出来,即使没有也会有比较成熟的方案。

如果集团内部就是没有成型方案,这个方向也属于工业界比较前沿的领域。遇到类似这种问题,可以先看看是否有绕开的可能性,如果确实绕不开可以试试找到适合解决该问题的基础团队一起合作和共建。外部是否有付费方案可以购买和借鉴,总之要保障业务先赢。因为业务工程师要思考的是你给业务能带来怎样的价值,你的核心价值不是处理非常复杂的技术问题,而是用你的技术能给业务带来怎样的价值增量。同样的利用某种技术或模型模式解决了非常复杂的业务问题,并且是具有普适价值的技术,这也是业务端工程师带给业务带来的价值。

3. 立足当下,放眼未来
知几,其神乎!

要看当下更要看未来,不光技术要看未来,行业也要看未来。站在当下思考能解决业务目前遇到的*大的问题,思考未来能为业务带来弯道超车的机会。比如飞猪如果在行业里要追赶同行业的竞品,在资源投入方面没办法跟对方的体量比较的情况下,我们做到*后,*好的结果可能也只是追平对手。所以我们亟须找到未来行业争胜的关键按钮,把时间和精力聚焦在关键节点,用全球Fun战略突围。所以飞猪也要为国际化做好准备,这个领域里同样有前人探寻的技术经验供我们借鉴。所以为了让我们能更聚焦业务,可以说去年的平台化是为业务做了非常好的铺垫。

*后的技术结果跟业务结果如何衔接?
其实这个小标题有点伪命题的意思,如果一开始我们就把业务理解的很清楚,执行没有偏离航道比较专注目标的话,不大可能会出现拿不到业务结果的情况,*后只剩下一个问题:拿到业务结果的同时技术价值如何体现?

从我自身出发,也常常有同学问我,在业务做开发,重复造轮子会被人挑战,但事情都有人干了我们的价值在哪?我之前一直都会回答,“搞基础技术的团队一直在基础工程/技术领域深耕,他们也需要关注从技术价值到业务价值的转变和衔接,本质上缺少业务场景,如果我们与他们合作就形成了互补,既拿到了业务结果同时也能从自身技术成长上得到一定历练”。

但之后我回想这段对话,是有很多问题在里面的。从业务工程师角度出发,我们要关注的核心就是保障业务先赢,如果没有达到这个目标就容易变成工程师自嗨。所以我们在业务端需要的是有技术视野能看到集团其他团队或者外部团队在做的事,能主动交流让这件事变成共赢,如果没有其他人在搞,我们去搞要有人站出来看这个投入产出比是否合理?也就是我们在开篇说的议题度和解答质都高的有价值的问题。这个问题在集团其他团队是否存在共性,我们解决了能否为他们带来价值?当然结合我们在前面讲到的在业务中发现有技术价值的问题,其实这里就有一个比较明确的答案,重中之重就是做之前把 Why 思考的清楚清晰,做*正确的事。只有做到这点,解决这个问题带来的业务价值就自然而然非常清晰的定位出来。所以说*好的工程师必须要懂产品。

也写给未来
小聊一下题外话,组里有同学会问我业务前端未来是否会被淘汰?因为我们在做的 lowcode/nocode 是在革自己的命。其实产生这种想法首先就是没有站在集团未来发展的角度去思考也就是常说的屁股太小,其次是没有站在整个前端领域去回顾前端发展历程导致的悲观和担忧。

从目前在做的方向上来说,还是要思考如何解决低质量代码建设和低效的重复工作占用工程师大部分精力,将工程师的能量解放出来提升集团整体的研发效能。另一层面从前端以往在系统分层里的位置一直都属于应用层,就是*上层的表象/展现/渲染,应用层在过去几十年间经过了不断的变化和演进,职业也从*早的 GUI 工程师演进到之后的 web 前端/客户端研发工程师,这中间也经历过 flash 工程师的时代,在此期间应用层/展现层一直都在变化,所以前端同学总觉得状态是一直在学习新知识。但这个发展历程其实是有规律可循的,所谓万变不离其宗,应用层虽然在不断变化但无非都是朝着两个大方向在发展,一个是工程效率提升(工程角度出发),一个是图形图像研究(用户角度出发)。这两个大方向上目前也有非常复杂庞大的树状知识体系,并且还在不断延伸。同时随着机器学习领域的兴起和硬件性能、网络带宽的提升以及人们在视觉呈现设备上的升级,带来的可能又是新一轮的技术洗牌,然后在两个方向上再来一次。所以从这个视角出发未来前端是不会消亡的可能只是会换一种形式存在,但是不学习的工程师是会消亡的。

*后
*后我想说的是来到一个新业务不要着急的去拿这两个结果(业务和技术),所谓“潜龙勿用”。要先去看业务在集团所处的位置,怎么和其他业务产生关联的,要去收集信息和问题,带着问题深入去做事情,通过跟其他人的信息交流补全业务痛点。先收集问题,边做边思考,先沉下心做业务项目。要有导弹型思维,就是不管三七二十一,先干起来再说。在行动中实现智能导航,锁定并跟踪目标,根据实际情况修正自身路径,直至击中目标。

其实写了比较多,也是对我做事情的方法论做了一遍梳理和总结,也是说*好不要让业务推着你走,而是*终要做到你带着业务走。这个“带”可能*初是理解业务打法之后的一种业务朝着你理解的方向去走的体感,但经过长期训练,这部分其实可以做实,*后真的是你通过技术创新引领行业变革*后驱动业务向前推进。当然这些是我来阿里三年的体会,虽然在来之前也已经工作了七八年,但在阿里成长的速度远远超过之前的成长,并且也才刚刚三年还是个“新人”,所以在这里也给自己个寄语,希望五年、十年之后我的思考又会升华到一个层次。同时也欢迎大家拍砖/评论, 原来我都是战战兢兢发文跟大家说轻拍,需要鼓励,但之后也是发现鼓励是*不容易发现问题,这会导致发现不了自身思考上的盲点和盲区,缺少成长路上的经验值,所以这里鼓励大家一起多交流。

*后的*后也给大家推荐相关的几本书,可能会对大家在上面几处没有展开来讲的去更详细的学习,希望有所帮助:《金字塔原理》、《麦肯锡教我的思考武器》、《思考,快与慢》、《影响力》、《自控力》、《敏捷性开发》。
————————————————

原文链接:https://blog.csdn.net/alisystemsoftware/article/details/107765100

Python系列11-Python文件操作

Python系列11-Python文件操作

文章目录
一.从文件中读取数据
1.1 读取整个文件
1.2 逐行读取
1.3 创建一个包含文件各行内容的列表
1.4 使用文件的内容
二. 写入文件
2.1 写入空文件
2.2 写入多行
2.3 附加到文件
三.存储数据
3.1 使用json.dump() 和json.load()
3.2 保存和读取用户生成的数据
3.3 重构
参考:
一.从文件中读取数据
文本文件可存储的数据量多得难以置信:天气数据、交通数据、社会经济数据、文学作品等。每当需要分析或修改存储在文件中的信息时,读取文件都很有用,对数据分析应用
程序来说尤其如此。例如,你可以编写一个这样的程序:读取一个文本文件的内容,重新设置这些数据的格式并将其写入文件,让浏览器能够显示这些内容。
要使用文本文件中的信息,首先需要将信息读取到内存中。为此,你可以一次性读取文件的全部内容,也可以以每次一行的方式逐步读取。

1.1 读取整个文件
要读取文件,需要一个包含几行文本的文件。
下面首先来创建一个文件,它包含关系型数据库的名称以及排名。

Oracle 1
MySQL 2
SQL Server 3
PostgreSQL 4

代码:
文件路径给一定要是’/’,’’会报错

with open(‘E:/python/file_test/db.txt’) as file_object:
contents = file_object.read()
print(contents)

测试记录:

Oracle 1
MySQL 2
SQL Server 3
PostgreSQL 4

1.2 逐行读取
读取文件时,常常需要检查其中的每一行:你可能要在文件中查找特定的信息,或者要以某种方式修改文件中的文本。

要以每次一行的方式检查文件,可对文件对象使用for 循环。

代码:

filename = ‘E:/python/file_test/db.txt’

with open(filename) as file_object:
for line in file_object:
print(line)

测试记录:

E:\python\learn_python1\venv\Scripts\python.exe E:/python/learn_python1/file_test1.py
Oracle 1

MySQL 2

SQL Server 3

PostgreSQL 4

Process finished with exit code 0

我们打印每一行时,发现空白行更多了
为何会出现这些空白行呢?因为在这个文件中,每行的末尾都有一个看不见的换行符,而print 语句也会加上一个换行符,因此每行末尾都有两个换行符:一个来自文件,另一
个来自print 语句。要消除这些多余的空白行,可在print 语句中使用rstrip().

代码:

filename = ‘E:/python/file_test/db.txt’

with open(filename) as file_object:
for line in file_object:
print(line.rstrip())

测试记录:

E:\python\learn_python1\venv\Scripts\python.exe E:/python/learn_python1/file_test1.py
Oracle 1
MySQL 2
SQL Server 3
PostgreSQL 4

Process finished with exit code 0

1.3 创建一个包含文件各行内容的列表
使用关键字with 时,open() 返回的文件对象只在with 代码块内可用。如果要在with 代码块外访问文件的内容,可在with 代码块内将文件的各行存储在一个列表中,并在with 代码块外使用该列表:你可以立即处理文件的各个部分,也可推迟到程序后面再处理。

代码:

filename = ‘E:/python/file_test/db.txt’

with open(filename) as file_object:
lines = file_object.readlines()

for line in lines:
print(line.rstrip())

测试记录:

E:\python\learn_python1\venv\Scripts\python.exe E:/python/learn_python1/file_test1.py
Oracle 1
MySQL 2
SQL Server 3
PostgreSQL 4

Process finished with exit code 0

1.4 使用文件的内容
将文件读取到内存中后,就可以以任何方式使用这些数据了。下面以简单的方式使用圆周率的值。首先,我们将创建一个字符串,它包含文件中存储的所有数字,且没有任何空格。

文件信息:

3.1415926535
8979323846
2643383279

代码:

filename = ‘E:/python/file_test/pi.txt’

with open(filename) as file_object:
lines = file_object.readlines()

pi_string = ”
for line in lines:
line_format = line.rstrip()
line_format = line_format.lstrip()
pi_string += line_format

print(pi_string)
print(len(pi_string))

测试记录:

E:\python\learn_python1\venv\Scripts\python.exe E:/python/learn_python1/file_test2.py
3.141592653589793238462643383279
32

Process finished with exit code 0

二. 写入文件
保存数据的*简单的方式之一是将其写入到文件中。通过将输出写入文件,即便关闭包含程序输出的终端窗口,这些输出也依然存在:你可以在程序结束运行后查看这些输出,可与别人分享输出文件,还可编写程序来将这些输出读取到内存中并进行处理。

2.1 写入空文件
要将文本写入文件,你在调用open() 时需要提供另一个实参,告诉Python你要写入打开的文件。为明白其中的工作原理,我们来将一条简单的消息存储到文件中,而不是将其打印到屏幕上。

代码:

filename = ‘E:/python/file_test/programming.txt’

with open(filename, ‘w’) as file_object:
file_object.write(“I love programming.”)

测试记录:

C:\>more E:\python\file_test\programming.txt
I love programming.

C:\>

2.2 写入多行
函数write() 不会在你写入的文本末尾添加换行符,因此如果你写入多行时没有指定换行符,文件看起来可能不是你希望的那样.

代码:

filename = ‘E:/python/file_test/programming.txt’

with open(filename, ‘w’) as file_object:
file_object.write(“I love programming.\n”)

测试记录:

C:\>more E:\python\file_test\programming.txt
I love programming.
I love creating new games.

C:\>

2.3 附加到文件
如果你要给文件添加内容,而不是覆盖原有的内容,可以附加模式 打开文件。你以附加模式打开文件时,Python不会在返回文件对象前清空文件,而你写入到文件的行都将添加到文件末尾。如果指定的文件不存在,Python将为你创建一个空文件。

代码:

filename = ‘E:/python/file_test/programming.txt’

with open(filename, ‘a’) as file_object:
file_object.write(“I also love finding meaning in large databases.\n”)
file_object.write(“I lowe creating apps that can run in a browser.\n”)

测试记录:

C:\>more E:\python\file_test\programming.txt
I love programming.
I love creating new games.
I also love finding meaning in large databases.
I lowe creating apps that can run in a browser.

三.存储数据
很多程序都要求用户输入某种信息,如让用户存储游戏首选项或提供要可视化的数据。不管专注的是什么,程序都把用户提供的信息存储在列表和字典等数据结构中。用户关闭程序时,你几乎总是要保存他们提供的信息;一种简单的方式是使用模块json 来存储数据。

模块json让你能够将简单的Python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据。你还可以使用json 在Python程序之间分享数据。更重要的是,JSON数据格式并非Python专用的,这让你能够将以JSON格式存储的数据与使用其他编程语言的人分享。这是一种轻便格式,很有用,也易于学习。

3.1 使用json.dump() 和json.load()
我们来编写一个存储一组数字的简短程序,再编写一个将这些数字读取到内存中的程序。*个程序将使用json.dump() 来存储这组数字,而第二个程序将使用json.load() 。

函数json.dump() 接受两个实参:要存储的数据以及可用于存储数据的文件对象。下面演示了如何使用json.dump() 来存储数字列.

代码:

import json

numbers = [2 ,3 ,5 ,7 ,11 ,13]

filename = ‘E:/python/file_test/numbers.json’
with open(filename, ‘w’) as f_obj:
json.dump(numbers, f_obj)

测试记录:

C:\>more E:\python\file_test\numbers.json
[2, 3, 5, 7, 11, 13]

C:\>

下面演示了如何使用json.load() 来读取数字列.
代码:

import json

filename = ‘E:/python/file_test/numbers.json’
with open(filename) as f_obj:
numbers = json.load(f_obj)

print(numbers)

测试记录:

E:\python\learn_python1\venv\Scripts\python.exe E:/python/learn_python1/venv/json_test1.py
[2, 3, 5, 7, 11, 13]

Process finished with exit code 0

3.2 保存和读取用户生成的数据
对于用户生成的数据,使用json 保存它们大有裨益,因为如果不以某种方式进行存储,等程序停止运行时用户的信息将丢失。下面来看一个这样的例子:用户首次运行程序时被提示输入自己的名字,这样再次运行程序时就记住他了。

我们先来存储用户的名字.

代码:

import json
# 如果以前存储了用户名,就加载它
# 否则,就用提示用户输入用户名并存储它

filename = ‘E:/python/file_test/username.json’

try:
with open(filename) as f_obj:
username = json.load(f_obj)
except FileNotFoundError:
username = input(“What is your name?”)
with open(filename, ‘w’) as f_obj:
json.dump(username, f_obj)
print(“We’ll remember you when you come back, ” + username + “!”)
else:
print(“Welcome back, ” + username + “!”)

测试记录:

— *次
E:\python\learn_python1\venv\Scripts\python.exe E:/python/learn_python1/json_test2.py
What is your name? Oracle
We’ll remember you when you come back, Oracle!

Process finished with exit code 0

— 第二次
E:\python\learn_python1\venv\Scripts\python.exe E:/python/learn_python1/json_test2.py
Welcome back, Oracle!

Process finished with exit code 0

3.3 重构
你经常会遇到这样的情况:代码能够正确地运行,但可做进一步的改进——将代码划分为一系列完成具体工作的函数。这样的过程被称为重构 。重构让代码更清晰、更易于理解、更容易扩展。

要重构json_test2.py,可将其大部分逻辑放到一个或多个函数中。json_test2.py的重点是问候用户,因此我们将其所有代码都放到一个名为greet_user() 的函数中,获取存量的用户名放在一个名为get_stored_username()的函数中,获取新的输入用户名的信息放在一个名为get_new_username()的函数中。

这样每个函数只做一件事情,greet_user() 没有过多的代码,直接调用其余的几个函数即可。

代码:

import json

def get_stored_username():
“””如果存储了用户名,就获取它”””
filename = ‘E:/python/file_test/username.json’
try:
with open(filename) as f_obj:
username = json.load(f_obj)
except FileNotFoundError:
return None
else:
return username

def get_new_username():
“””提示用户输入用户”””
username = input(“What is your name?”)
filename = ‘E:/python/file_test/username.json’
with open(filename, ‘w’) as f_obj:
json.dump(usernmae, f_obj)
return username

def greet_user():
“””问候用户,并指出其名字”””
username = get_stored_username()
if username:
print(“Welcome back, ” + username + “!”)
else:
username = get_new_username()
print(“We’ll remeber you when you come back, ” + username + “!”)

greet_user()

测试记录:

E:\python\learn_python1\venv\Scripts\python.exe E:/python/learn_python1/json_test2.py
Welcome back, Oracle!

Process finished with exit code 0

参考:
1.Python编程:从入门到实践

python实现读取pdf格式文档

文章目录
一、 准备工作
二、部分变量的含义
三、PDFMiner类之间的关系
四、代码实现
python实现读取pdf格式文档
一、 准备工作
安装对应的库
pip install pdfminer3k
pip install pdfminer.six

二、部分变量的含义
PDFDocument(pdf文档对象)
PDFPageInterpreter(解释器)
PDFParser(pdf文档分析器)
PDFResourceManager(资源管理器)
PDFPageAggregator(聚合器)
LAParams(参数分析器)

三、PDFMiner类之间的关系%title插图%num

PDFMiner的相关文档(点击跳转)

四、代码实现
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# datetime:2021/3/17 12:12
# software: PyCharm
# version: python 3.9.2

def changePdfToText(filePath):
“””
解析pdf 文本,保存到同名txt文件中

param:
filePath: 需要读取的pdf文档的目录
introduced module:
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LAParams
from pdfminer.pdfdocument import PDFDocument, PDFTextExtractionNotAllowed
import os.path
“””
file = open(filePath, ‘rb’) # 以二进制读模式打开
# 用文件对象来创建一个pdf文档分析器
praser = PDFParser(file)
# 创建一个PDF文档
doc = PDFDocument(praser, ”) # praser :上面创建的pdf文档分析器 ,第二个参数是密码,设置为空就好了
# 连接分析器 与文档对象
praser.set_document(doc)
# 检测文档是否提供txt转换,不提供就忽略
if not doc.is_extractable:
raise PDFTextExtractionNotAllowed
# 创建PDf 资源管理器 来管理共享资源
rsrcmgr = PDFResourceManager()
# 创建一个PDF设备对象
laparams = LAParams()
device = PDFPageAggregator(rsrcmgr, laparams=laparams)
# 创建一个PDF解释器对象
interpreter = PDFPageInterpreter(rsrcmgr, device)
result = [] # 内容列表
# 循环遍历列表,每次处理一个page的内容
for page in PDFPage.create_pages(doc):
interpreter.process_page(page)
# 接受该页面的LTPage对象
layout = device.get_result()
for x in layout:
if hasattr(x, “get_text”):
result.append(x.get_text())
fileNames = os.path.splitext(filePath) # 分割
# 以追加的方式打开文件
with open(fileNames[0] + ‘.txt’, ‘a’, encoding=”utf-8″) as f:
results = x.get_text()
# print(results) 这个句可以取消注释就可以在控制台将所有内容输出了
f.write(results) # 写入文件

# 调用示例 :

# path = u’E:\\1.pdf’
# changePdfToText(path)

新手必看,史上*全的iOS开发教程集锦,没有之一!

*近大火的iPhone XS Max和iPhone XS,不知道有没有同学已经下手了呢?一万三的价位确实让很多人望而却步啊。据说为了赢得中国的用户,专门出了双卡双待的,可想而知中国市场这块“肥肉”人人都想要。

近几年,无论苹果出什么样的产品以及多高的价位,都会有非常多的苹果“死忠粉”去购买,iOS系统也是全球认可的*流畅性的系统。越来越多的人使用iPhone系列产品,同时给我们设计师和开发师带来了更多的创造性和可能性,可以赚到更多的钱啦。

作为一名混迹iOS开发圈近3年的码农,在这条路上走过了许多弯路,好在网上有很多优秀的教程、视频以及各种iOS学习资源,让我可以成功的独立开发一款iOS app应用。下面我就分享下这3年以来我觉得*好的20个iOS开发学习教程和资源,提供给大家参考,欢迎大家补充。

首先,要了解iOS开发语言

iOS目前流行两种开发语言:Objective-C 和 Swift 。前者有C语言基础者上手会容易些;后者Swift是iOS/Mac未来开发的主要语言,无论从编程思想还是从api书写,都很不错。Objective-C是一门面向对象的语言,并且是非常实用的语言。不管OC和Swift未来究竟如何发展,学习一门新的语言的本质,是接受一种新的思考方式。以下会涵盖两种语言教程供大家选择。

其次,要会利用iOS开发工具

Xcode

Xcode 是iOS 开发必备工具, Xcode运行于苹果公司的Mac操作系统下,是苹果公司向开发人员提供的集成开发环境,用于开发Mac OS X,iOS的应用程序。Xcode 具有统一的用户界面设计,编码、测试、调试都在一个简单的窗口内完成。当然你也可以使用APPcode。

CocoaPods

CocoaPods应该是iOS*常用*有名的类库管理工具了,通过CocoaPods工具我们可以为项目添加被称为“Pods”的依赖库(这些类库必须是CocoaPods本身所支持的),并且可以轻松管理其版本。

Mockplus

原型设计是在APP开发过程中必不可少的一步,或许你会觉得这是设计师的工作,和你无关。但为了和设计师们更好的沟通,学习原型设计是非常有必要的。并且只需要花费你几小时甚至更短的时间就能掌握一款简单易用的原型设计工具,何乐而不为呢。

*后,也是*重要的10个*佳的iOS开发学习教程

1. iOS (iPhone, iPad) Tutorial

https://www.tutorialspoint.com/iOS/

本教程专为需要使用Objective-C语言开发iOS上的iPhone和iPad应用程序而设计。在学习本教程之前,你需要对计算机编程术语有基本的了解。对任何编程语言(尤其是Objective-C编程语言)的基本理解将帮助你更快地学习iOS编程的概念。

2. Learn iOS Programming

https://www.appcoda.com/iOS-programming-course/

在这里,你可以找到一系列免费教程,这些教程是针对不具备任何编码经验的初学者,也可以是具有一些iOS编程经验的开发人员。列出的所有教程都是完全免费的,只需按照教程即可开始你的iOS开发之旅。

3. iOS11&Swift4-the complete iOS app development bootcamp

https://www.udemy.com/iOS-11-app-development-bootcamp/

本教程无需任何代码基础知识,使用Xcode 9和Swift 4包括完整的ARKit和CoreML模块!

你可以学习到:

  • 构建你想要的任何iOS应用程序
  • 制作一系列应用程序以申请初级开发人员工作
  • 为你的创业公司或业务构建完善的应用程序
  • 作为自由iOS开发人员工作

4. The Swift programming language Swift 4.2

https://Swift.org/

本教程是专门学习Swift,从基础知识到高阶语言,你所想要了解和学习关于Swift的都可以在这里获取到。对于学生来说,学习Swift是对现代编程概念的一个很好的入门介绍。 而且由于它是开放的,他们的Swift技能将能够应用于更广泛的平台,从移动设备到桌面再到云端。

5. Swift Tutorial Part 1: Expressions, Variables and Constants

https://www.raywenderlich.com/6338-Swift-tutorial-part-1-expressions-variables-and-constants

本教程是Swift的入门解说以及分解。对于本教程,你需要Xcode 10,这是MacOS的标准开发环境, 如果你是Xcode版本9或更低版本,本教程中的一些代码将无法运行。

6. Beginners iOS Development: Objective-C Guide for Developers

https://www.iOS-blog.com/tutorials/Objective-C/beginners-iOS-development-Objective-C/

本教程是关于Objective-C的初学者指南,适用于已经了解面向对象编程的iOS开发人员,并涵盖了Objective-C中你需要了解的所有概念,以便使用该语言学习iOS和OS X的编程。

7. Learn Cocoa

http://cocoadevcentral.com/d/learn_cocoa/

本教程教你如何从零开始创建一个Cocoa的应用程序,无需任何编程和Xcode经验。

8. Developing iOS 10 Apps with Swift by Stanford

https://itunes.apple.com/us/course/developing-iOS-10-apps-with-Swift/id1198467120

从完全不了解Swift,Xcode和iOS开发 到你将掌握使用Swift,MVC架构以及其他方面的基础知识!

9. Learning iOS development on GitHub

github.com/search?q=iO…

你可以在GitHub上学习到你想了解iOS开发的所有知识和资源,还可以上传自己的源代码以及查看开源项目,阅读别人的代码是*好的学习方式。

10. App Development Tutorial | How to Make An iOS APP (2018)

https://www.youtube.com/playlist?list=PL6cactdCCnTIzhUomNgV3i8jgxk0ExxPk

这是一个iOS开发的系列视频教程,包含Udemy Tech频道所有发布过的iOS11,Swift4,Xcode9视频,视频是不断更新的,讲解都很到位。

10个*佳iOS开发学习网站

1. Swift by Robin Eggenkamp

Swift.zeef.com/robin.eggen…该网站收集了很多关于 Swift 的学习资料, 新闻。

2. iOS Dev Weekly

iOSdevweekly.com/

每周一期,内容多为这一星期里值得关注的 iOS 项目、文章、工具等。

3. Swiftweekly

https://Swiftweekly.com/

一个专门学习Swift的网站,有教程、视频以及案列分析。

4. iOS Developer Library

developer.apple.com/documentati…

iOS 开发必看, 有此文档足矣, 内容非常之详细。

5. Awesome iOS

iOS.libhunt.com/

Awesome iOS会向你发送iOS Programming subreddit中流行的iOS的库以及热门资讯,网站还分享许多非常有用的iOS资源和*受欢迎的文章,问题,Reddit讨论,并都会直接发送到你的收件箱哦。

6. objc

www.objc.io/

Objc致力于创建一个与所有iOS和macOS开发人员相关的深入技术主题讨论平台。每周都会发布优秀的视频来展示和讨论在Swift中构建项目时遇到的问题以及解决方案。

7. Nshipster

https://nshipster.com/

NSHipster是专门分享关于Objective-C,Swift和Cocoa期刊,每周更新。

8. Ole Begemann’s Blog

Ole Begemann’s Blog

Ole是来自柏林的iOS和Mac开发师, 他自2009年以来就在Apple平台上撰写了关于软件开发的文章。尽管他每年只发表一些文章,但所有文章都值得一读。

9. Swift developer blog

http://Swiftdeveloperblog.com/

这是一个专门学习Swift的个人网站,网站除了有优质的文章以外,还有视频教程以及代码案列可供参考。如果你想要学习Swift的一切,那么这个网站你值得收藏。

10. iOS goodies

https://iOS-goodies.com/post/178728323086/week-250

这个网站每周会选取*新的iOS开发文章、工具,视频、还有关于UI/UX设计的相关资讯,现已更新了250周了,内容非常丰富,能全部看完*对可以成为一名优秀的iOS开发师。

总结

学习iOS开发并不是一件难事,只要你有坚持下去的信心以及浓厚的兴趣,或者你想要赚更多的钱也可以,总之要有信念。其次,你要有一台Mac电脑,基础的标配哦。*后当然是看以上20个iOS开发的学习教程和资源,助你更快地成为一名初级的iOS开发师。

pandas数值运算方法

pandas数值运算方法

1、通用函数:保留索引:
对Series或DataFrame对象使用numpy的通用函数时,返回的是保留索引的pandas对象

2、通用函数:索引对齐:
当两个Series或DataFrame对象进行二元计算时,pandas会在计算过程中自动,对齐两个对象的索引。

1.Series索引对齐,结果输出的是,索引的并集,但是只有交集才有计算结果,其他返回为空,当然,也可以设置空值,

添加fill_value参数,进行填补空值。若两个都是空值,则不进行填充(必须使用通用函数,例如add、sub)

2.DataFrame索引对齐,结果同上,只不过是同时对齐 列索引 和 行索引 。就算是顺序不同,结果的索引都会自动排列的。

若想补充空值,同样的使用通用函数,添加fill_value参数即可

运算符 通用函数
+ add()
– sub()、subtract()
* mul()、multiply()
/ div()
// floordiv()
% mod()
** pow()
以上通用函数,前面可以加一个r(例如radd()),表示顺序颠倒1+2变为2+1

3、通用函数:Series和DataFrame的计算

Series和DataFrame进行计算时,默认是从行上面减的(axis=1),若想在列上面减,可以使用通用函数,设置axis=0即可

他们进行计算时,与前面的一样,都是进行索引自动对其的。

服务器的分类

服务器这块的知识是我的知识体系的一个薄弱点,花点时间对三类服务器(PC服务器,小型机,大型机)作一下梳理。

服务器分类的标准有很多,比如按照处理器架构来分可以分为x86服务器、RISC构架服务器和IA-64服务器;按照处理器个数来分可以分为单路、双路和多路服务器;按照服务器的外形结构来分可以分为塔式服务器、机架式服务器和刀片服务器;按照应用级别来分类,可以分为工作组级、部门级和企业级服务器。

按处理器架构分类
下图为IBM服务器体系的划分,这虽然代表了IBM对自身产品线的定位,但也体现了三类服务器的市场定位。

2014年1月23日 消息,联想宣布,以23亿美元收购IBM低端服务器业务,包括20.7亿美元现金,以及1.82亿股联想集团股份。
所以现在IBM的PC服务器已经是联想的了。

联想集团董事长兼CEO杨元庆表示,并购将为联想每年带来50亿美元的营收,联想服务器业务的市场份额将由全球第六上升到第三。 这是继联想2004年收购IBM个人电脑业务后,双方再次发生并购交易。

PC服务器(或叫x86服务器)
基于Intel处理器的x86架构,通用开发的处理器架构。x86系统*早起源于8086芯片组,而芯片组的主处理器是由Intel和AMD所制造。随后,越来越多的厂商将该芯片应用到台式机,笔记本以及服务器上。如今的企业服务器市场上,少数几家厂商占据了*大多数的市场份额。目前,市场上主流的x86服务器包括:

1.IBM x系列服务器

2.HP Proliant DL/ML以及BL服务器

3.NEC Express服务器

4.Dell PowerEdge

5.Sun(Oracle) Sun Fire和Netra

X86服务器的操作系统可以有很多选择,可以是Enterprise Linux,也可以是Windows Server系列。就像前面说的那样,Sun还把原本只应用于小型机的Solaris移植到了X86平台。

x86服务器各家厂商的市场份额

综观2012年全年X86市场,虽然从整体份额上看,IBM 、DELL、HP仍占有X86市场过半江山。

%title插图%num

IBM X系列x86服务器型号的简介

%title插图%num

System X系列服务器型号有四位数字:3xxx后两位是“00”的表示该服务器是塔式机箱,“50”表示,机架式设计,另外有一款特殊的X3610,是X3650的简化版,也是2U机架式的,但是精简掉了很多功能。 前两位大概代表了该服务器的性能指标,其中“31”和“32”是一路服务器,如3100、3250等,这类服务器只能安装一颗CPU。
“34”“35”“36”如3400、3550、3650都是两路服务器,即可以安装2颗CPU,
“38”和“39”是多路服务器,单机支持4路CPU,通过扩展组件可以实现16块CPU的密度,这是业界基于X86构架服务器的*高CPU密度。
另外还有一个不太常见的系列,就是结尾两位是“55”的服务器,如X3755等,这些服务器是基于AMD皓龙CPU的,国内很少出货。 一般31xx~32xx级别的System X都是用作简单的应用,如打印服务器,文件共享服务器等;
34xx~36xx级别的可以用作部门级的应用,如边界应用服务器,小型ERP,CRM,域控服务器等;
38xx和39xx可以算得上PC服务器里的“战斗机”了,性能可以和低端System p比肩,一般用作后端数据库服务器,大规模ERP应用,或者高CPU密度的计算任务等。

小型机
小型机是指采用8-32颗处理器,超过32GB的海量内存容量,性能和价格介于PC服务器和大型主机之间的一种高性能 64 位计算机。国外小型机对应英文名是minicomputer和midrange computer。在服务器市场中小型机处于中高端位置。

在中国,小型机习惯上用来指UNIX服务器,所以可见小型机的操作系统多是Unix系的操作系统。几大厂商都Unix服务器多为自己的特有系统,如,IBM的AIX,HP的HP-UX,SUN的Solaris,这些操作系统面向基于RISC指令集的硬件。并且UNIX操作系统和硬件通常是由同一家制造商开发。

%title插图%num

(上图为IBM P750)

下边这张三国鼎立图说明了,现在小型机市场主要是由IBM,HP,Oracle(Sun)三大公司所把持。其中IBM凭借Power 6、7、8芯片暂居*对优势。%title插图%num

三大公司的主要产品:

1.IBM的POWER系列,采用POWER6和POWER7芯片处理器,运行AIX操作系统。
2.HP的Integrity系列,采用由HP和INTEL联合开发的Itanium(安腾)处理器,运行HP-UX。
3.Oracle-SUN系统,采用SPARC芯片处理器架构,运行Solaris操作系统。

(由于Solaris操作系统被移植到了x86平台上,SUN的定义就有些模糊,其实SUN还是区别于x86和基于RISC指令集的SPARC系统的,是被作为SPARC中的企业级系统。)

特性:

小型机的性能和价格介于PC服务器和大型主机之间的一种高性能 64 位计算机。小型机跟普通的PC服务器是有很大差别的,*重要的一点就是小型机的高RAS(Reliability, Availability, Serviceability 高可靠性、高可用性、高服务性)特性。
RAS是Reliability, Availability, Serviceability三个英文单词的缩写,它们反映了计算机的高可靠性、高可用性、高服务性三个著名特点,它们的具体含义如下:
高可靠性(Reliability):计算机能够持续运转,从来不停机。
高可用性(Availability):重要资源都有备份;能够检测到潜在要发生的问题,并且能够转移其上正在运行的任务到其它资源,以减少停机时间,保持生产的持续运转;具有实时在线维护和延迟性维护功能。
高服务性(Serviceability):能够实时在线诊断,精确定位出根本问题所在,做到准确无误的快速修复。

去小型机化

在以往的印象当中,x86服务器在中低端形成了统治之势,而小型机则在关键性应用领域(金融、证券、政府等)享有王者地位。但是随着X86服务器的不断发展,这两年来“去小型机化”的趋势趋于明显,众多金融、电信、政府等用户正逐渐将更多的应用迁移到x86平台。随着X86服务器在架构、制程工艺、核心数量等方面不断的提升,性能直追小型机,更廉价、更开放、更加标准化、更简单易用的优点也让用户越来越乐于接受。小型机在关键任务中的宝座似乎也不再那么稳固了。

大型机
大型机(Mainframe)的功能、价格以及性能上都在小型机和x86服务器之上,是一种用于大规模计算的计算机系统。大型机通常用于政府、银行、交通、保险公司和大型制造企业。特点是处理数据能力强大、稳定性和安全性又非常高。

大型机的特点是处理数据能力强大、稳定性和安全性又非常高。

目前,市场上主流的大型机有两家:IBM和UNISYS。IBM大型机是其z系列服务器。顺便说下,Sun和HP不生产大型机,但它们生产性能和用途类似于IBM大型机的高端Unix服务器。

现在IBM主推的z系列的大型机是:IBM  zEnterprise大型服务器主机。

%title插图%num

按服务器外形分类
按照服务器的外形结构来分可以分为塔式服务器、机架式服务器和刀片服务器。

%title插图%num

按处理器数量分类
“路”都是指服务器物理CPU的数量,也就是服务器主板上CPU插槽的数量。

单路:指服务器支持1个CPU
双路:指服务器支持2个CPU
四路:指服务器支持4个CPU
多路:指服务器支持多个CPU

双核,就是将两个计算内核集成在一个硅晶元上。从而提高计算能力。多核就是将多个计算内核集成在一个硅晶元上。

双路(英文缩写为SMP)则是采用两颗相同型号并且能够支持SMP技术的CPU组成的一套系统。指在一台计算机上汇集了一组处理器,多个CPU共享计算机内存子系统及总线架构。在这种架构中,同时由多个处理器运行操作系统的单一复本,并共享内存和一台计算机的其他资源,系统将任务队列对称地分布于多个CPU之上,从而*大地提高了整个系统的数据处理能力。所有的处理器都可以平等地访问内存、I/O和外部中断。在对称多处理系统中,系统资源被系统中所有CPU共享,工作负载能够均匀地分配到所有可用处理器之上。我们平时所说的双路CPU系统,实际上是对称多处理系统中*常见的一种形式,常用于主流的X86服务器和图形工作站领域。

*简单的说法,双核=1颗CPU有两个核心,双路=两个对称的CPU(这颗CPU也可以是双核的CPU)。

另外,服务器选择中的CPU配置方式。
小型企业:1~2路处理器
中型企业:2~4路处理器
大型企业:4~8路处理器

%title插图%num

服务器分解图

%title插图%num

分享一下自己的手机从ios14降级回ios13.5.1

关于ios14降级后点击图片和网页分享页面出现空白的情况
需要还原系统设置,这样子会重置当前的所有设置(不会清除数据)。

通用—还原—还原所有设置(会重启)

%title插图%num
下面是修复问题后的样子

%title插图%num
升级ios14测试版
6月22号凌晨ios14测试版推出后,上午立马给我的小7装上尝尝鲜。
想要尝试的请下载描述文件,iphone和ipad通用。

https://www.firedev.xyz/14/iOS_iPadOS_14_AppleSeed_Profile.mobileconfig

注意:使用Safari浏览器(iphone自带的)

ios14主要的不同点是:
App资源库,可以智能分类
小组件,主屏幕和负一屏
画中画,这个实测仅限apple TV可以使用
接下来的一段时间让我深刻体会到了什么是测试版,噩梦开始了
手机发热(堪比某米)
掉电巨快
有时莫名的卡顿
系统占用内存的变大
*让我受不了的还是前面两点
ios14降回ios13.5.1
昨天晚上实在是受不了,决定倒退系统

准备工作
itunes(用来备份手机和还原)
ios13.5.1固件包
1、备份
建议啊,icloud基本备份一下!!!!!!
微信和QQ的聊天记录备份,可以先备份到电脑上,双重保险。
由于 iOS 系统限制,跨版本降级会导致设备数据丢失,理论上从 iOS 14 备份的数据也无法恢复至 iOS 13 系统,你现在用爱思助手或者 iTunes 备份的数据,降回 iOS 13 是无法恢复的。

1.1、首先,在 iOS 14 系统下通过 iTunes 完整备份你的 iPhone 资料。

%title插图%num

如果找不到这个页面,请点击这个手机小图标

%title插图%num
1.2、备份完成后,打开刚刚备份的文件
windows:C:Users/用户名/AppData/Roaming/Apple Computer/MobileSync/Backup

打开*新的备份文件夹,用记事本/文本编辑工具打开info.plist
(文件被删除了,就不上图了)

Ctrl+F 查找Product Version

在这个字段的下一行就是关于IOS备份的版本号了,因为是在ios14下备份的嘛,这个就是14了

<kev>Product Version</kev>
<string>14.0</string>
<key>Serial Number</key>

把中间的14.0修改为13.5.1,也就是要降级的系统版本。注意啊,这个版本号千万不要写错!!!!!
2、固件包
2.1、在爱思助手官网上下载相应的固件包

%title插图%num

3、使用itunes进行降级

%title插图%num
打开 iTunes,按住 shift(windows)键,点恢复 iPhone,在弹出窗口中选择下载好的 iOS 13.5.1 系统固件等待刷机完成即可

实测
除了邮件账户需要重新添加,别的数据都在。(也可能是icloud有基本备份)
成功了的小伙伴帮我点一下赞噢

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速