日期: 2021 年 5 月 8 日

如何把握云计算时代风口 怎么能掌握云计算技术

如何把握云计算时代风口?怎么能掌握云计算技术?随着国家政策支持以及互联网的高速发展,我国云计算技术迅速火爆并获得广泛应用。分析预计,预计到2021年公有云市场规模将达到902.6亿元,私有云市场规模将达到955.7亿元。很多人想要把握云计算时代风口,但在关注云计算技术之余,掌握因云计算而火爆的技术也很重要。接下来就给大家简单介绍一下。

%title插图%num

1、无服务器

在2014年AWS公司推出无服务器架构之前,云计算客户猜测了他们需要配置并相应付费的计算资源级别。而使用无服务器时,AWS公司只向客户收取实际使用的费用。更重要的是,使用无服务器,云计算提供商可以处理维护和扩展方面的基础设施难题,从而使客户(尤其是开发人员)更轻松、更快地构建其基于云计算的系统。无服务器也被称为功能即服务,允许应用程序在云平台更快、更高效地运行。

2、微服务

微服务将笨重的整体应用程序分解为许多更小的、联合的服务或“模块”,在2012年开始风靡一时。它使用模块化方法,由团队根据需要更新模块,独立于整个庞大的应用程序。微服务可以持续交付*新更新的软件。与无服务器一样,它允许应用程序以云计算时代所需的更快速度发展。

3、容器

2014年春季,容器技术应运而生。而容器可以使软件开发更快、更敏捷,业界对此充满了好奇。容器并不是什么新事物,但是广为人知的Docker使它们易于使用。与Vmware公司推出的虚拟机(必须容纳整个操作系统)不同,容器将多个软件包装在一个软件容器中,就像一个轻巧的“手提箱”。容器本身承载软件,并且仅包含所需的基本要素(库和配置),其文件在计算环境之间移动。

4、DevOps

说到持续交付,DevOps的重点是持续集成(CI)/持续交付(CD)。DevOps于2012年开始获得强劲发展,它既是一种技术转变,也是一种文化转变。其目标是通过开发团队和运营团队这两个世界观截然不同的团队相互交流来加速软件开发。

5、物联网(IoT)

物联网和云计算通常都是独立运行,但这两种技术有着不可分割的联系。

首先,物联网厂商不能从头开始构建所有内容,因为太昂贵且太复杂,因此采用云计算技术,而每个主要的云计算提供商都提供物联网解决方案。此外,有关物联网(也称为“边缘计算”)的关键问题是:将在哪里处理所有数据?对于许多企业而言,其答案是“在我们的云平台中”。由云计算提供商的超大规模服务器提供支持的基于云计算的数据分析可提供出色的数据处理能力。

6、人工智能

凭借其可以独立于工作人员协助而学习的软件的承诺,人工智能成为一款强大的工具,其巨大的潜力使所有其他工具相形见绌。当人工智能独立于云计算的存在时,人工智能对于企业来说是非常复杂的。随着云计算的成熟,基于云计算的人工智能使得一些具有远见卓识的中小型公司可以实现自己的愿景,就像财力雄厚的大公司一样。

如果你想成为一个合格的云计算人才,想快速掌握云计算一系列的技术,可以选择专业学习一下。专业的学习让你高效、快速掌握企业所需的高薪技术!

Android auto 对接步骤

1、在对应工程的manifest里添加支持Androidauto的注册信息:

<application>

<meta-data android:name=”com.google.android.gms.car.application” android:resource=”@xml/automotive_app_desc”/>

<application>

其中automotive_app_desc.xml路径为res/xml/下,信息内容如下:

<automotiveApp>

<uses name=”media”/>

</automotiveApp>

 

2、在工程的manifest里声明media browser service,内容例如:

<application>

<service android:name=”.MyMediaBrowserService” android:exported=”true”>

<intent-filter> <action android:name=

“android.media.browse.MediaBrowserService”/> </intent-filter>

</service>

<application>

3、如果需要通知,可以在manifest里添加对应的通知内容,例如:

<application>

<meta-data android:name=”com.google.android.gms.car.notification.SmallIcon” android:resource=”@drawable/ic_notification” />

<!–如果要支持搜索,需要添加搜索消息–>

<activity> <intent-filter>

<action android:name= “android.media.action.MEDIA_PLAY_FROM_SEARCH” />

<category android:name= “android.intent.category.DEFAULT” />

</intent-filter>

</activity>

<application> 4、新建自己的MediaBrowserService,该service要继承MediaBrowserServiceCompat,主要实现以下内容:

1)、在onCreate里注册media session、注册音乐状态相关的回调、设置当前的session和关联回调

public void onCreate() {
。。。。。

//具体处理Androidauto相关的逻辑

mProvider = new AutoMediaProvider(this, this);

//注册media session

mSession = new MediaSessionCompat(this, TAG);

//设置session和播放器的关联

mPlayer = new AutoPlayerManager(this, mSession, mProvider, this);

setSessionToken(mSession.getSessionToken());

mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS

| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

// 设置seesion的回调和播放状态的回调关联

mSession.setCallback(new AutoSessionCallback(this, mSession, mPlayer, mProvider));

。。。。。。

}

 

2)、针对media连接状态做相应的处理,(比如此时APP本身在播放音乐,Androidauto连接上了,并来了播放消息,此时应该让之前的停止,只播放Androidauto的播放)*好在定义的MediaBrowserService里注册下面的广播:

IntentFilter filter = new IntentFilter(“com.google.android.gms.car.media.STATUS”); BroadcastReceiver receiver = new BroadcastReceiver() {
。。。。。。

public void onReceive(Context context, Intent intent) {
String status = intent.getStringExtra(“media_connection_status”); boolean isConnectedToCar = “media_connected”.equals(status);

// adjust settings based on the connection status

}

};

registerReceiver(receiver, filter);

 

3)、针对onGetRoot、onLoadChildren、onLoadItem(目前没用到),填入获取到的目录列表信息、歌曲信息到MediaBrowserCompat.MediaItem里,返回给Androidauto。其中将APP本身的目录列表转换为MediaBrowserCompat.MediaItem时需要自己制定相关规则,然后下一级目录解析的时候又按照之前的规则解析出来:例如目前我们转化的方式为将基本信息按照信息间添加“-”转化为STRING作为MediaId,然后再按照“-”将传过来的MediaId解析出来,作下一次请求:

{
。。。。。

AutoMediaId id = AutoMediaId.buildMediaId(channel.getType(), null, null,AutoMediaId.MEDIA_ITEM_FLAG_CHANNEL, null);

Bundle extras = new Bundle();

id.putExtra(extras);

MediaDescriptionCompat desc = new MediaDescriptionCompat.Builder()

.setMediaId(id.toString())

.setTitle(channel.getName())

.setIconUri(Uri.parse(“http://www.easyicon.net/api/resizeApi.php?id=1206029&size=128”))

.setExtras(extras)

.build();

 

MediaBrowserCompat.MediaItem item = new MediaBrowserCompat.MediaItem(desc, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE);//FLAG_BROWSABLE为目录,如果想后面结束目录FLAG_PLAYABLE,后面Androidauto就会直接调用播放相关的消息。

。。。。。

}

 

public static final String SPLITOR = “-“;

/** bundle keyword media TAG: channel */

public static final String MEDIA_TAG_CHANNEL = “CHN”;

/** bundle keyword media TAG: album */

public static final String MEDIA_TAG_ALBUM = “ABM”;

/** bundle keyword media TAG: album */

public static final String MEDIA_TAG_ID = “ID”;

/** bundle keyword media TAG: level */

public static final String MEDIA_TAG_LEVEL = “LVL”;

/** bundle keyword media TAG: extra */

public static final String MEDIA_TAG_EXTRA = “EXTRA”;

public String toString() {
String mediaId = “”;

if (TextUtils.isEmpty(mId)) {
return mediaId;

}

 

mediaId = MEDIA_TAG_ID + mId;

 

mediaId += TextUtils.isEmpty(mChannel) ? “” : SPLITOR + MEDIA_TAG_CHANNEL + mChannel;

mediaId += TextUtils.isEmpty(mAlbum) ? “” : SPLITOR + MEDIA_TAG_ALBUM + mAlbum;

mediaId += TextUtils.isEmpty(mLevel) ? “” : SPLITOR + MEDIA_TAG_LEVEL + mLevel;

mediaId += TextUtils.isEmpty(mExtra) ? “” : SPLITOR + MEDIA_TAG_EXTRA + mExtra;

return mediaId;

}

解析方式:

public static AutoMediaId parseMediaId(String mediaId) {
AutoMediaId media = new AutoMediaId();

if (TextUtils.isEmpty(mediaId)) {
return media;

}

String[] elements = mediaId.split(SPLITOR);

for (int i = 0; i < elements.length; i++) {
if (elements[i].startsWith(MEDIA_TAG_CHANNEL)) {
media.mChannel = elements[i].substring(MEDIA_TAG_CHANNEL.length());

} else if (elements[i].startsWith(MEDIA_TAG_ALBUM)) {
media.mAlbum = elements[i].substring(MEDIA_TAG_ALBUM.length());

} else if (elements[i].startsWith(MEDIA_TAG_ID)) {
media.mId = elements[i].substring(MEDIA_TAG_ID.length());

} else if (elements[i].startsWith(MEDIA_TAG_LEVEL)) {
media.mLevel = elements[i].substring(MEDIA_TAG_LEVEL.length());

} else if (elements[i].startsWith(MEDIA_TAG_EXTRA)) {
media.mExtra = elements[i].substring(MEDIA_TAG_EXTRA.length());

}

}

return media;

}

 

5、新建自己的AutoSessionCallback,该callback继承MediaSessionCompat.Callback,实现onPlayFromMediaId、onPlayFromUri、 onPlay()、onPause()、 onStop()、onPlayFromSearch、 onSkipToPrevious()、onSkipToNext()、onSeekTo(long pos)、onCustomAction(String action, Bundle extras)等主要方法。

 

其中onPlayFromSearch提供的是Androidauto的搜索接口;另外,如果要展示播放列表,需要将mSession里添加MediaSessionCompat.QueueItem;如果要添加自定义的icon操作,要在mSession里添加 PlaybackStateCompat.Builder,PlaybackStateCompat.Builder 里添加statBuilder.addCustomAction。

怎么掌握云计算核心技术 Docker容器怎么回事

怎么掌握云计算核心技术?Docker容器怎么回事?Docker容器是一个开源的应用容器引擎,随着云计算的迅猛发展而被人们熟知。一个合格的云计算工程是一定要熟练掌握Docker容器技术,接下来小编就给大家梳理汇总Docker容器相关知识。

%title插图%num

Docker主要有如下几个概念:

引擎:创建和管理容器的工具,通过读取镜像来生成容器,并负责从仓库拉取镜像或提交镜像到仓库中;

镜像:类似于虚拟机镜像,一般由一个基本操作系统环境和多个应用程序打包而成,是创建容器的模板;

容器:可看作一个简易版的Linxu系统环境(包括root用户权限、进程空间、用户空间和网络空间等)以及运行在其中的应用程序打包而成的盒子;

仓库:集中存放镜像文件的场所,分为公共仓库和私有仓库,目前*大的公共仓库是官方提供的Docker Hub,此外国内的阿里云、腾讯云等也提供了公共仓库;

宿主机:运行引擎的操作系统所在服务器。

Docker镜像采用分层存储格式,每个镜像可依赖其他镜像进行构建,每一层的镜像可被多个镜像引用。这种分层结构能充分共享镜像层,能大大减少镜像仓库占用的空间,而对用户而言,他们所看到的容器,其实是Docker利用UnionFS(联合文件系统)把相关镜像层的目录“联合”到同一个挂载点呈现出来的一个整体。

什么是UnionFS?UnionFS可以把多个物理位置独立的目录(也叫分支)内容联合挂载到同一个目录下,UnionFS允许控制这些目录的读写权限,此外对于只读的文件和目录,它具有“Copy on Write(写实复制)”的特点,即如果对一个只读的文件进行修改,在修改前会先把文件复制一份到可写层(可能是磁盘里的一个目录),所有的修改操作其实都是对这个文件副本进行修改,原来的只读文件并不会变化。

UnionFS有很多种,其中Docker中常用的是AUFS,这是UnionFS的升级版,除此之外还有DeviceMapper、Overlay2、ZFS和 VFS等。Docker镜像的每一层默认存放在/var/lib/docker/aufs/diff目录中,当用户启动一个容器时,Docker引擎首先在/var/lib/docker/aufs/diff中新建一个可读写层目录,然后使用UnionFS把该可读写层目录和指定镜像的各层目录联合挂载到/var/lib/docker/aufs/mnt里的一个目录中(其中指定镜像的各层目录都以只读方式挂载),通过LXC等技术进行环境隔离和资源控制,使容器里的应用仅依赖mnt目录中对应的挂载目录和文件运行起来。

利用UnionFS写实复制的特点,在启动一个容器时, Docker引擎实际上只是增加了一个可写层和构造了一个Linux容器,这两者都几乎不消耗系统资源,因此Docker容器能够做到秒级启动,一台服务器上能够启动上千个Docker容器,而传统虚拟机在一台服务器上启动几十个就已经非常吃力了,而且虚拟机启动很慢,这是Docker相比于传统虚拟机的两个巨大的优势。

Docker镜像制作方法

1)通过正在运行的容器生成新镜像。当一个容器在运行时,在里面所有的修改都会体现在容器的可写层,Docker提供了commit命令,可以把正在运行的容器,叠加上可写层的修改内容,生成一个新镜像。

2)通过Dockerfile文件来生成新镜像。Dockerfile是一个定义了镜像创建步骤的文件,Docker引擎通过build命令读取Dockerfile,按定义的步骤来一步步构造镜像。在研发和实施环境中,通过Dockerfile 创建容器是主流做法。

如果你想了解更多Docker容器技术,想快速加入云计算开发行列,你可以选择专业学习一下,让自己快速系统的掌握企业所需的云计算核心技术!

云计算开源工具有哪些 如何快速加入高薪行列

云计算开源工具有哪些?如何快速加入高薪行列?随着互联网的高速发展以及国家政策扶持,我国云计算行业发展迅猛,云计算人才也成为稀缺高薪人才。为了能够快速入行,很多人会选择专业学习一下,这已经成为大多数人的选择。

众所周知,云计算和开源是相爱相生的关系,借助开源社区的力量,云计算技术迅速占领市场,不过2020年常用的云计算开源工具有哪些呢?接下来就给大家介绍一下。

%title插图%num

1、Kubernetes

过去两年Kuberentes已成为火爆的开源项目之一,相信在未来Kuberentes的势头会更劲,其拥有大量的扩展工具,其优势在于:

1)通过基于角色的访问控制可以更好地支持企业部署;

2)将Kuberentes从单一用户操作系统转移到Unix;

3)支持在Kubernetes管理的容器和容器中运行有状态应用。

除了Kuberentes容器调度器外,CNCF(云原生基金会)还提供了一套广泛的兼容工具,用于操作和交付现代分布式系统,这些组合创建的功能可以扩展到成千上万个自修复的多租户节点上,同时还可以实现操作上的差异。

2、Fluentd

Fluentd是一个免费,而且完全开源的日志管理工具,简化了日志的收集、处理、和存储,可以不需要在维护编写特殊的日志处理脚本。Fluentd的性能已经在各领域得到了证明:目前*大的用户从5000+服务器收集日志,每天5TB的数据量,在高峰时间处理50000条信息每秒。

3、Prometheus

Prometheus(简称Prom)前身是SoundCloud的告警工具包,现已演化成一个独立的开源监控系统。它是一种度量标准的监控系统,旨在为监视服务提供云本地的方法。主要特性:1)多维度数据模型;2)时间序列数据通过metric名和键值对来区分,所有的metrics都可以设置任意的多维标签;3)数据模型随意,不需要刻意设置为以点分隔的字符串等。

4、Linkerd

Linkerd是一款开源网络代理,旨在作为服务网格进行部署:专用层,用于在应用程序内管理,控制和监视服务到服务的通信。通过为服务提供统一,统一的仪器和控制层,Linkerd免费服务所有者选择*适合其服务的语言。通过将通信机制与应用程序代码分离,Linkerd允许在不改变应用程序本身的情况下查看和控制这些机制。

5、CoreDNS

CoreDNS的前身是SkyDNS,它的主要目的是构建一个快速灵活的DNS服务器,让用户可以通过不同方式访问和使用DNS内的数据。它被设计为Caddy网络服务的一个服务器插件。CoreDNS的每个特性都可以被实现为可插拔的中间件,如日志、基于文件的DNS以及多种后端技术,进而可以拼接多个插件来创建定制化的管道。CoreDNS已经得到扩展,可以直接被Kubernetes访问服务数据,并以KubeDNS的形式提供给用户使用。

当然,除了以上工具,2020年比较常用的云计算开源工具还包括Containerd、gRPC、OpenTracing等。熟练掌握各种开源工具会让你在求职时更具优势,而想要快速加入到云计算这一高薪行列,参加专业学习是一个不错的选择。

云数据库六大优势是什么 如何学好云计算技能

云数据库六大优势是什么?如何学好云计算技能?数据库是前端还是后台开发人员都需要了解和掌握的工具,传统的数据库工程师需要掌握基础理论知识、数据库基础知识、数据库运维知识以及数据库性能调优技能。不过随着云时代的到来,云数据库的应用及大规模普及,给数据库工程师的日常工作带来了很大的积*影响,下面就给大家详细介绍一下云数据库的六大优势:

%title插图%num

1、免部署。云数据库种类丰富,关系型数据库如MySQL、PostgreSQL、SQL Server,非关系型数据库如MongoDB、Redis、Memcache,兼容和支持各种版本。通过简单的购买操作,分钟级甚至秒级交付,云数据库一键部署。

2、高性能。云数据库软硬件深度调优,具有理想的性能表现。同时,底层硬件较快引入*新高性能硬件,多种性能加持下,DBA可聚焦在应用层优化。

3、高可靠性。云数据库能够自动探测,及时容灾,保证数据库服务不中断。对于数据库工程师来说,也不需要再额外部署高可用架构。

4、强大的灵活性和扩展性。云数据库弹性扩展的能力,至少是支持垂直扩展(scale-up),通常也支持水平扩展(scale-out)。灵活性则是第三维度的扩展,它可以支持一主多从,读写分离。数据库工程师能够在短期内聚焦业务,暂时不会有扩展性的烦恼。

5、自带运维能力。云数据库通常支持自动备份和手动备份两种模式,提供一键回档的功能找回数据。并提供详细的监控数据,也可配置异常自动告警。可以说,数据库工程师对云数据库基本没有运维工作。

6、安全可靠。云数据库在数据存储、网络链路访问、鉴权认证、多租户隔离方面做了多重保障,以确保数据安全,除此之外,它可以支持数据库审计,后端自动漏洞扫描,定期安全加固等。

使用云数据库后,数据库工程师可以有更多时间关注其他技能的锻炼和培养,提升自己的综合竞争力。如果你想了解更多云计算技术,可以选择专业学习一下。

Python爬虫Scrapy轮子工具

Python爬虫Scrapy轮子工具

Scrapy
万字长文,建议使用目录点击查阅,有助于高效开发。建议点赞收藏

文章目录
Scrapy
概念
模块作用
开发步骤
爬虫文件 spiders.py
代码流程
提取数据
scrapy.Request发送post请求
发送post请求
response响应
Cookie
参数解释
meta参数的使用
管道 piplines.py
pipeline中常用的方法:
开启管道
多个管道的开启作用
MongoDB 持久化
Json 持久化
MySql 持久化
Csv持久化
中间件 middleware.py
中间件的分类
Scrapy中间的作用(预处理Request和Response对象)
Downloader Middlewares默认的方法:
fake_useragent
ip_proxy
方法一【免费代理】:
方法二【收费代理】:
Scrapy-redis
Scrapy-bloomfilter布隆过滤器
设置 settings.py
常用变量
启动运行
方法一【运行单个爬虫文件】:
方法二【 串行 运行完*个才会运行下一个】:
方法三【在进程里面跑多个爬虫】:
概念
scrapy框架的运行流程以及数据传递过程:

爬虫中起始的url构造成request对象–>爬虫中间件–>引擎–>调度器
调度器把request–>引擎–>下载中间件—>下载器
下载器发送请求,获取response响应—->下载中间件—->引擎—>爬虫中间件—>爬虫
爬虫提取url地址,组装成request对象—->爬虫中间件—>引擎—>调度器,重复步骤2
爬虫提取数据—>引擎—>管道处理和保存数据
模块作用
引擎(engine):负责数据和信号在不腰痛模块间的传递
调度器(scheduler):实现一个队列,存放引擎发过来的request请求对象
下载器(downloader):发送引擎发过来的request请求,获取响应,并将响应交给引擎
爬虫(spider):处理引擎发过来的response,提取数据,提取url,并交给引擎
管道(pipeline):处理引擎传递过来的数据,比如存储
下载中间件(downloader middleware):可以自定义的下载扩展,比如设置代理ip
爬虫中间件(spider middleware):可以自定义request请求和进行response过滤,与下载中间件作用重复

开发步骤
创建项目:

scrapy startproject mySpider
scrapy startproject <项目名字>

生成一个爬虫【在项目目录下执行】:

scrapy genspider lianjia lianjia.com
scrapy genspider <爬虫名字> <允许爬取的域名>

爬虫名字: 作为爬虫运行时的参数

允许爬取的域名: 为对于爬虫设置的爬取范围,设置之后用于过滤要爬取的url,如果爬取的url与允许的域不通则被过滤掉。

提取数据:

修改start_urls
检查修改allowed_domains
编写解析方法
根据网站结构在spider中实现数据采集相关内容

保存数据:

在pipelines.py文件中定义对数据处理的管道

在settings.py文件中注册启用管道

启动项目

爬虫文件 spiders.py
代码流程
完善并使用Item数据类:
在items.py中完善要爬取的字段
在爬虫文件中先导入Item
实力化Item对象后,像字典一样直接使用
构造Request对象,并发送请求:
导入scrapy.Request类
在解析函数中提取url
yield scrapy.Request(url, callback=self.parse_detail, meta={})
利用meta参数在不同的解析函数中传递数据:
通过前一个解析函数 yield scrapy.Request(url, callback=self.xxx, meta={}) 来传递meta
在self.xxx函数中 response.meta.get(‘key’, ‘’) 或 response.meta[‘key’] 的方式取出传递的数据
提取数据
解析并获取scrapy爬虫中的数据:
1. response.xpath方法的返回结果是一个类似list的类型,其中包含的是selector对象,操作和列表一样,但是有一些额外的方法
2. extract() 返回一个包含有字符串的列表,配合[0]使用
3. extract_first() 返回列表中的*个字符串,列表为空没有返回None
4. get() 提取列表中第1个文本内容(等同于extract_first())

scrapy.Request发送post请求
我们知道可以通过scrapy.Request()指定method、body参数来发送post请求;但是通常使用scrapy.FormRequest()来发送post请求
1
发送post请求
注意:scrapy.FormRequest()能够发送表单和ajax请求,参考阅读 https://www.jb51.net/article/146769.htm

response响应
response.url:当前响应的url地址

1. response.request.url:当前响应对应的请求的url地址
2. response.headers:响应头
3. response.requests.headers:当前响应的请求头
4. response.body:响应体,也就是html代码,byte类型
5. response.status:响应状态码

Cookie
1.在settings.py中通过设置COOKIES_DEBUG=TRUE 能够在终端看到cookie的传递传递过程
2.如果start_url地址中的url是需要登录后才能访问的url地址,则需要重写3.start_request方法并在其中手动添加上cookie
4.如果重新start_requests()方法,则需要去掉start_urls变量

参数解释
中括号里的参数为可选参数
callback:表示当前的url的响应交给哪个函数去处理
meta:实现数据在不同的解析函数中传递,meta默认带有部分数据,比如下载延迟,请求深度等
dont_filter:默认为False,会过滤请求的url地址,即请求过的url地址不会继续被请求,对需要重复请求的url地址可以把它设置为Ture,比如贴吧的翻页请求,页面的数据总是在变化;start_urls中的地址会被反复请求,否则程序不会启动
method:指定POST或GET请求
headers:接收一个字典,其中不包括cookies
cookies:接收一个字典,专门放置cookies
body:接收json字符串,为POST的数据,发送payload_post请求时使用(在下一章节中会介绍post请求)
注意:解析函数中的yield能够传递的对象只能是:BaseItem, Request, dict, None
meta参数的使用
meta的作用:meta可以实现数据在不同的解析函数中的传递
在爬虫文件的parse方法中,提取详情页增加之前callback指定的parse_detail函数:

def parse(self,response):

yield scrapy.Request(detail_url, callback=self.parse_detail,meta={“item”:item})

def parse_detail(self,response):
#获取之前传入的item
item = resposne.meta[“item”]

注意
1. meta参数是一个字典
2. meta字典中有一个固定的键proxy,表示代理ip,关于代理ip的使用我们将在scrapy的下载中间件

管道 piplines.py
管道的基本使用:
1. 完善pipelines.py中的process_item函数
2. 在settings.py中设置开启pipeline
3. pipeline在setting中键表示位置(即pipeline在项目中的位置可以自定义),值表示距离引擎的远近,越近数据会越先经过:权重值小的优先执行
4. 1. 有多个pipeline的时候,process_item的方法必须return item,否则后一个pipeline取到的数据为None值
5. pipeline中process_item的方法必须有,否则item没有办法接受和处理
6. process_item方法接受item和spider,其中spider表示当前传递item过来的spider

pipeline中常用的方法:
process_item(self,item,spider):
管道类中必须有的函数
实现对item数据的处理
必须return item
open_spider(self, spider): 在爬虫开启的时候仅执行一次
close_spider(self, spider): 在爬虫关闭的时候仅执行一次
开启管道
在settings.py设置开启pipeline
1
ITEM_PIPELINES = {
‘myspider.pipelines.ItcastFilePipeline’: 400, # 400表示权重
‘myspider.pipelines.ItcastMongoPipeline’: 500, # 权重值越小,越优先执行!
}

多个管道的开启作用
1. 不同的pipeline可以处理不同爬虫的数据,通过spider.name属性来区分
2. 不同的pipeline能够对一个或多个爬虫进行不同的数据处理的操作,比如一个进行数据清洗,一个进行数据的保存
3. 同一个管道类也可以处理不同爬虫的数据,通过spider.name属性来区分

MongoDB 持久化
# 【1】settings.py中添加
ITEM_PIPELINES = {
# 添加MongoDB管道
‘Tencent.pipelines.TencentMongoPipeline’: 400,
}
MONGO_HOST = ‘127.0.0.1’
MONGO_PORT = 27017
MONGO_DB = ‘tencentdb’
MONGO_SET = ‘tencentset’

# 【2】pipelines.py中新建MongoDB管道类
from .settings import *
import pymongo

class TencentMongoPipeline:
def open_spider(self, spider):
self.conn = pymongo.MongoClient(MONGO_HOST, MONGO_PORT)
self.db = self.conn[MONGO_DB]
self.myset = self.db[MONGO_SET]

def process_item(self, item, spider):
self.myset.insert_one(dict(item))

Json 持久化
import json

class WangyiPipeline(object):

def open_spider(self, spider):
if spider.name == ‘job’:
self.file = open(‘wangyi.json’, ‘w’)

def process_item(self, item, spider):
if spider.name == ‘job’:
item = dict(item)

str_data = json.dumps(item, ensure_ascii=False) + ‘,\n’

self.file.write(str_data)

return item

def close_spider(self, spider):
if spider.name == ‘job’:
self.file.close()

MySql 持久化
1)MySQL建表

create database tencentdb charset utf8;
use tencentdb;
create table tencenttab(
job_name varchar(200),
job_type varchar(200),
job_duty varchar(2000),
job_require varchar(2000),
job_add varchar(100),
job_time varchar(100)
)charset=utf8;

2)MySql数据持久化

# 【1】settings.py添加
ITEM_PIPELINES = {
# 在原来基础上添加MySQL的管道
‘Tencent.pipelines.TencentMysqlPipeline’: 200,
}
MYSQL_HOST = ‘127.0.0.1’
MYSQL_USER = ‘root’
MYSQL_PWD = ‘123456’
MYSQL_DB = ‘tencentdb’
CHARSET = ‘utf8’

# 【2】pipelines.py新建MySQL管道类
from .settings import *
import pymysql

class TencentMysqlPipeline:
def open_spider(self, spider):
self.db = pymysql.connect(MYSQL_HOST, MYSQL_USER, MYSQL_PWD, MYSQL_DB, charset=CHARSET)
self.cur = self.db.cursor()
self.ins = ‘insert into tencenttab values(%s,%s,%s,%s,%s,%s)’

def process_item(self, item, spider):
li = [
item[‘job_name’],
item[‘job_type’],
item[‘job_duty’],
item[‘job_require’],
item[‘job_add’],
item[‘job_time’],
]
self.cur.execute(self.ins, li)
self.db.commit()

return item

def close_spider(self, item, spider):
self.cur.close()
self.db.close()

进阶:mysql连接池
Csv持久化
piplines.py
import csv

class LianjiaspiderPipeline(object):
def open_spider(self, spider):
if spider.name == “home”:
self.file = open(‘lianjia.csv’, ‘w’, encoding=”utf-8″)
self.f_csv = csv.writer(self.file)
headers = [‘地址’, ‘总价’, ‘单价’, ‘户型’, ‘面积’, “朝向”, “楼层”, “装修程度”, “详情页url”]
self.f_csv.writerow(headers)

def process_item(self, item, spider):
if spider.name == “home”:
data = [item[“address”], item[“price”], item[“unit_price”], item[“door_model”], item[“area”],
item[“direction”], item[“floor”], item[“decorate”], item[“info_url”]]
self.f_csv.writerow(data)
print(data)
return item

def close_spider(self, spider):
if spider.name == “home”:
self.file.close()

settings.py
# 管道
ITEM_PIPELINES = {
‘LianJiaSpider.pipelines.LianjiaspiderPipeline’: 300,
}

中间件 middleware.py
中间件的分类
1.下载器中间件
2.爬虫中间件

Scrapy中间的作用(预处理Request和Response对象)
1. 对header以及cookie进行更换和处理
2. 使用代理ip等
3. 对请求进行定制化操作,

但在scrapy默认的情况下 两种中间件都在middlewares.py一个文件中

爬虫中间件使用方法和下载中间件相同,且功能重复,通常使用下载中间件

Downloader Middlewares默认的方法:
process_request(self, request, spider):

当每个request通过下载中间件时,该方法被调用。
2. 返回None值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其他权重低的process_request方法
3. 返回Response对象:不再请求,把response返回给引擎
4. 返回Request对象:把request对象通过引擎交给调度器,此时将不通过其他权重低的process_request方法
process_response(self, request, response, spider):

当下载器完成http请求,传递响应给引擎的时候调用
2. 返回Resposne:通过引擎交给爬虫处理或交给权重更低的其他下载中间件的process_response方法
3. 返回Request对象:通过引擎交给调取器继续请求,此时将不通过其他权重低的process_request方法
在settings.py中配置开启中间件,权重值越小越优先执行

fake_useragent
middlewares.py
from fake_useragent import UserAgent
class RandomUserAgentMiddleware(object):
def process_request(self, request, spider):
ua = UserAgent()
request.headers[‘User-Agent’] = ua.random

settings.py
DOWNLOADER_MIDDLEWARES = {
‘xxx项目名.middlewares.RandomUserAgentMiddleware’: 300,
}

注意:UserAgent中间件设置为None,这样就不会启用,否则默认系统的这个中间会被启用。

ip_proxy
方法一【免费代理】:
settings.py
DOWNLOADER_MIDDLEWARES = {
‘项目名.middlewares.RandomProxy’: 543,
}
PROXY_LIST =[
{“ip_port”: “123.207.53.84:16816”, “user_passwd”: “morganna_mode_g:ggc22qxp”},
# {“ip_port”: “122.234.206.43:9000”},
]

middlewares.py
from 项目名.settings import PROXY_LIST

class RandomProxy(object):

def process_request(self, request, spider):
proxy = random.choice(PROXY_LIST)
print(proxy)
if ‘user_passwd’ in proxy:
# 对账号密码进行编码,python3中base64编码的数据必须是bytes类型,所以需要encode
b64_up = base64.b64encode(proxy[‘user_passwd’].encode())
# 设置认证
request.headers[‘Proxy-Authorization’] = ‘Basic ‘ + b64_up.decode()
# 设置代理
request.meta[‘proxy’] = proxy[‘ip_port’]
else:
# 设置代理
request.meta[‘proxy’] = proxy[‘ip_port’]

方法二【收费代理】:
收费代理ip:

# 人民币玩家的代码(使用abuyun提供的代理ip)
import base64

# 代理隧道验证信息 这个是在那个网站上申请的
proxyServer = ‘http://proxy.abuyun.com:9010’ # 收费的代理ip服务器地址,这里是abuyun
proxyUser = 用户名
proxyPass = 密码
proxyAuth = “Basic ” + base64.b64encode(proxyUser + “:” + proxyPass)

class ProxyMiddleware(object):
def process_request(self, request, spider):
# 设置代理
request.meta[“proxy”] = proxyServer
# 设置认证
request.headers[“Proxy-Authorization”] = proxyAuth

检测代理ip是否可用
在使用了代理ip的情况下可以在下载中间件的process_response()方法中处理代理ip的使用情况,如果该代理ip不能使用可以替换其他代理ip

class ProxyMiddleware(object):
……
def process_response(self, request, response, spider):
if response.status != ‘200’:
request.dont_filter = True # 重新发送的请求对象能够再次进入队列
return requst

settings.py
DOWNLOADER_MIDDLEWARES = {
‘myspider.middlewares.ProxyMiddleware’: 543,
}

Scrapy-redis
settings.py 文件配置[注意:scrapy-redis 与 bloomfilter 二者只能选其一使用]
# scrapy-redis分布式配置 pip install scrapy-redis
# 重新指定调度器: 启用Redis调度存储请求队列!!!
SCHEDULER = “scrapy_redis.scheduler.Scheduler”
# 重新指定去重机制: 确保所有的爬虫通过Redis去重!!!
DUPEFILTER_CLASS = “scrapy_redis.dupefilter.RFPDupeFilter”

# redis配置
REDIS_HOST = ‘127.0.0.1’ # ip
REDIS_PORT = 6379 # 端口
# REDIS_PARAMS = {
# ‘password’: ”, # 密码
# }

Scrapy-bloomfilter布隆过滤器
settings.py文件配置
# 布隆过滤器配置 pip install scrapy-redis-bloomfilter
# 重新指定调度器
SCHEDULER = “scrapy_redis_bloomfilter.scheduler.Scheduler”
# 重新指定去重机制
DUPEFILTER_CLASS = “scrapy_redis_bloomfilter.dupefilter.RFPDupeFilter”
# 使用哈希函数的数量,默认为6
BLOOMFILTER_HASH_NUMBER = 6
# 使用Bloomfilter的Redis内存,30表示2^30 = 128MB,默认为30
BLOOMFILTER_BIT = 30

设置 settings.py
常用变量
设置数据导出编码(主要针对于json文件)
FEED_EXPORT_ENCODING = ‘utf-8’
设置User-Agent
USER_AGENT = ”
设置*大并发数(默认为16)
CONCURRENT_REQUESTS = 32
下载延迟时间(每隔多长时间请求一个网页)
DOWNLOAD_DELAY = 0.5
请求头
DEFAULT_REQUEST_HEADERS = {‘Cookie’ : ‘xxx’}
添加项目管道
ITEM_PIPELINES = {‘目录名.pipelines.类名’ : 优先级}
COOKIES_ENABLED = False

启动运行
方法一【运行单个爬虫文件】:
在根目录下创建start.py

from scrapy import cmdline

cmdline.execute(“scrapy crawl hot”.split())
# cmdline.execute(“scrapy crawl hot -o hot.csv”.split()) # 导出csv

# cmdline.execute(“scrapy crawl hot -o hot.json”.split()) # 导出json

# 注意: settings.py中设置导出编码 – 主要针对json文件
FEED_EXPORT_ENCODING = ‘utf-8’

Excel打开csv时出现乱码

解决办法:用记事本打开CSV,文件菜单中另存为UTF-8保存
方法二【 串行 运行完*个才会运行下一个】:
在根目录下创建main.py

from scrapy.cmdline import execute

execute(“scrapy crawl 爬虫文件名1”.split())
execute(“scrapy crawl 爬虫文件名2”.split())

方法三【在进程里面跑多个爬虫】:
在根目录下创建main.py

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

settings = get_project_settings()

crawler = CrawlerProcess(settings)

crawler.crawl(‘爬虫文件名1’)
crawler.crawl(‘爬虫文件名2’)

crawler.start()
crawler.start()

UE4 Python脚本编辑器扩展

UE4 Python脚本编辑器扩展

Python+编辑器扩展

1. 各种菜单的扩展
1.1 主菜单内添加一个子菜单
mainMenu = menus.find_menu(‘LevelEditor.MainMenu’) // 找到主菜单

ownerName = mainMenu.get_name()
# 该名称用于标识一个菜单下的分区名,如果menu的sectionName一致,它们会被放在一起
sectionName = ‘PythonTools’
subMenuName = ‘MenuTest’
subMenuLabel = ‘MenuTest1’
subMenuTip = ‘This is menutest1’
menus.add_sub_menu(ownerName, sectionName, subMenuName, subMenuLabel, subMenuTip)
# 刷新窗口
menus.refresh_all_widgets()

想要查看ue编辑器内的各个sectionname,可以在EditorPreference中的Misc中打开相应配置,打开一个菜单时会刷新对应的widget,如果想要窗口全部刷新则可以执行如下python命令
py unreal.ToolMenus.get().refresh_all_widgets()

1.2 菜单项下添加一个按钮
menus = unreal.ToolMenus.get()
# 根据上面的subMenuName找到目标菜单
targetMenu = menus.find_menu(‘LevelEditor.MainMenu.MenuTest’)

menuEntry = unreal.ToolMenuEntry(type=unreal.MultiBlockType.MENU_ENTRY)
menuEntry.set_label(‘Test Button 1’)
menuEntry.set_string_command(unreal.ToolMenuStringCommandType.PYTHON, ”, ‘print(‘this is button 1′)’)

sectionname = ”
targetMenu.add_menu_entry(sectionname, menuEntry)
menus.refresh_all_widgets()

按钮的命令:
unreal.ToolMenuStringCommandType.PYTHON,后面的字符串为python代码;
unreal.ToolMenuStringCommandType.COMMAND,后面的字符串为cmd命令,如使用py xxx.py执行脚本;
等同于输出日志中的python控制台和cmd控制台的py命令;

1.3 为ToolBar添加按钮
# 和上面的两个区别,首先是targetMenu,然后是Entry的类型
targetMenu = menus.find_menu(‘LevelEditor.ToolEditorToolBar’)
menuEntry = unreal.ToolMenuEntry(type=unreal.MultiBlockType.TOOL_BAR_BUTTON)
1
2
3
1.4 内容浏览器右键菜单扩展
targetMenu = unreal.ToolMenus.get(‘ContentBrowser.FolderContextMenu’)
entry = unreal.ToolMenuEntry(type=unreal.MultiBlockType,MENU_ENTRY)

# 选中的资源
unreal.ContentBrowserAssetContextMenuContext.get_selected_objects()

1.5 关卡视口中actor右键菜单
可以用如下方式获取选中的actor,但是无法像蓝图一样将actor强转到相应的派生类,因此也就无法获取到实例actor的属性以及不能调用相应的函数;目前的python是不支持这个的,可参考:https://answers.unrealengine.com/questions/938515/casting-a-blueprint-in-python.html;
只能调用actor类已有的内置函数,如set_actor_location()等;

assets = unreal.EditorLevelLibrary.get_selected_level_actors()
for actor in assets:
1
2
但是可以修改bp的默认值,如下所示:
我们需要调用unreal.get_default_object来获取CDO(Class Default Object),然后使用set_editor_property来完成功能;

bp_class = unreal.load_class(None, ‘/Game/NewBlueprint.NewBlueprint_C’)
cdo = unreal.get_default_object(bp_class)
cdo.set_editor_property(‘var’, 102)
cdo.call_method(‘TestFunc’, (actor,))

上述列出的问题虽然python内不能解决,但是能够通过蓝图扩展来完成;
基于python的扩展依然还只是在pie中使用;

2. 基础实践
2.1 日志系统
unreal.log() : python中的print也会在内部通过unreal.log()来处理
unreal.log_warning()
unreal.log_error()
2.2 处理资源
如果需要在项目中处理资源,必须使用Unreal Python API来完成,而不能使用Python内置模块来处理磁盘资源文件,比如资源的移动,如果不适用unreal的api则会导致引用失效,所以要尽量使用unreal.EditorAssetLibrary或unreal.AssetTools

尽可能使用虚幻类型
比如数学类等,要尽可能使用Unreal API提供的类型,如unreal.Vector()

2.3 使用json配置来管理各种扩展
os.open/read/write
import json
json.dumps/loads

3.其它常用api
3.1 资源相关
资源相关的api都在这个库里:unreal.EditorAssetLibrary
资源的保存:save_asset()

3.2 工程路径
系统库:unreal.SystemLibrary
获取项目路径:get_project_directory()

4.结合pyqt5的进阶实践
本想使用ue4的api来打开一个文件对话框,但是没有找到,网上有一些使用C++的扩展;
因此就想到了pyqt5也可以完成,而且ue4也可以调用python,这样就不用在C++层处理了,但是这只能用于编辑器模式下;

4.1 打开一个文件对话框
import unreal
import os
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QToolTip, QPushButton, QMessageBox, QDesktopWidget, QFileDialog, QLabel)

class Example(QFileDialog):

def __init__(self):
super().__init__()
self.open_folder()

def open_folder(self):
path = QFileDialog.getExistingDirectory(self, u’选择文件夹’, unreal.SystemLibrary.get_project_directory())
print(path)

app = QApplication(sys.argv)
ex = Example()
sys.exit(app.quit())

5. 常见问题
5.1 Python missing classes from unreal module
一些模块没有找到是因为我们需要安装对应的插件
我们可以使用如下方式可以遍历到unreal下所有的子模块

import unreal
moduels = dir(unreal)
for module in modules:
print(module)

Python基础入门:九大必学点

Python基础入门:九大必学点

小编整理了一天,希望对想学习的朋友用,认真看与学,你就能敲会简单的码,学习上也就能事功半倍,下面就是本章的内容大概,喜欢就一定要收藏起来。

缩进
Python 函数没有明显的 begin 和 end,没有标明函数的开始和结束的花括号。唯一的分隔符是一个冒号 (?,接着代码本身是缩进的。

例子:

#函数
def func(value):
print value #缩进
if value == 1:
value += 1
elif value == 2:
pass
else:
value += 10

标识符
变量是标识符的例子。 标识符 是用来标识 某样东西 的名字。在命名标识符的时候,你要遵循这些规则:

1.python中的标识符是区分大小写的。

2.标示符以字母或下划线开头,可包括字母,下划线和数字,大小写敏感

3.以下划线开头的标识符是有特殊意义的。

•以单下划线开头(_foo)的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用“from xxx import *”而导入;
•以双下划线开头的(foo)代表类的私有成员;
•以双下划线开头和结尾的(foo)代表python里特殊方法专用的标识,如__init()代表类的构造函数。

4.标识符不能是保留字

and elif global or yield
assert else if pass
break except import print
class exec in raise
continue finally is return
def for lambda try
del from not while

变量
赋值语句
•赋值语句建立对象引用值
•变量名在首次赋值时会被建立
•变量名在引用前必须先赋值,不能引用未声明赋值的变量

赋值方式
•简单赋值
Variable(变量)=Value(值)
s = ‘spam’

•多变量赋值
python中原始的元组和列表赋值语句形成,*后已被通用化,以接受右侧可以是是任何类型的序列,只要长度相等即可。注意,长度一定相等
Variable1,variable2,…=Value1,Value2,…
s,h = ‘a’,‘b’ 元组赋值,位置性 【常用】
[s,h] =[‘a’,‘b’] 列表赋值,位置性
a,b,c,d = ‘spam’ 序列赋值,通用性
a,*b = ‘spam’ 拓展序列解包(python3)

•多目标赋值
a=b=variable
s = h = ‘spam’ 多目标赋值
注意:多个变量内存中指向同一对象,对于可变类型需要,修改一个会对其他造成影响

•自变赋值
如+=,-=,*=等。
在自变赋值中,python仅计算一次,而普通写法需计算两次;
自变赋值会修改原始对象,而不是创建一个新对象。
s +=42 增强赋值
x += y
优点:
程序员输入更少
左侧只需计算一次,优化技术自动原处修改,更快
l +=[] 原处修改
l = l+[] 复制,生成新的对象

运算符
一个表达式可以分解为运算符和操作数

运算符 的功能是完成某件事,它们由如+这样的符号或者其他特定的关键字表示
运算符需要数据来进行运算,这样的数据被称为 操作数
运算符优先顺序列表(从*高到*低)
运算符的描述

‘expr’ 字符串转换
{key:expr,…} 字典
[expr1,expr2…] 列表
(expr1,expr2,…) 元组
function(expr,…) 函数调用
x[index:index] 切片
x[index] 下标索引取值
x.attribute 属性引用
~x 按位取反
+x,-x 正,负
x**y 幂
x*y,x/y,x%y 乘,除,取模
x+y,x-y 加,减
x<<y,x>>y 移位
x&y 按位与
x^y 按位异或
x|y 按位或
x<y,x<=y,x==y,x!=y,x>=y,x>y 比较
x is y,x is not y 等同测试
x in y,x not in y 成员判断
not x 逻辑否
x and y 逻辑与
x or y 逻辑或
lambda arg,…:expr Lambda匿名函数
结合规律

运算符通常由左向右结合,即具有相同优先级的运算符按照从左向右的顺序计算

计算顺序
默认地,运算符优先级表决定了哪个运算符在别的运算符之前计算。然而,如果你想要改变它们的计算顺序,你得使用圆括号。好的做法:默认对复杂的运算加括号,而不是依赖于默认结合和计算顺序

真值
真值测试
•任何非零数字或非空对象都为真
•数字零,空对象以及特殊对象None都为假
•比较和相等测试都会递归地运用到数据结构中
•比较和相等测试会返回True或False
真值表

对象/常量 值
“” 假
“string” 真
0 假
2>=1 真
-2<=-1 真
()空元组 假
[]空列表 假
{}空字典 假
None 假

布尔表达式
三种布尔表达式运算符

x and y
x or y
not x

比较
•数字通过相对大小进行比较
•字符串时按照字典顺序的,一个字符一个字符比较
•列表和元组从左到右对每部分的内容进行比较
•字典通过排序后的键值列表进行比较
•数字混合类型比较在python3是错误的,但是python2.6支持,固定但任意的排序规则
布尔数
•有两个永远不改变的值True,False
•布尔是整型的子类,但不能被再继承
•没有__nonzero__()方法的对象的默认值是True
•对于值为0的任何数字或空集,值False
•在数学运算中,Bollean值的True和False分别对应于1和0

基本控制流
if
基本的条件测试语句,用来判断可能遇到的不同情况,并针对不同的情况进行操作
基本形式

if <条件>:
<语句>
elif <条件>:
<语句>
else:
<语句>

注意
python根据缩进判断, elif和else部分是可选的

例子:

a = 1
b = 2
c = 3;d=4 #两个放一句用分号隔开,不过建议分行
if a < b and c < d:
print(“branch a”)
elif a == b:
print(“branch b”)
else:
print(“branch c”)
switch

python 本身没有 switch 语句,若需要,用if/elif/else实现完成同样的工作,某些情况可以考虑用字典
也可以用dict的形式
if/else三元运算符
A = ((X and Y) or Z)
A = Y if X else Z
例: a = ‘t’ if x else ‘a’
for
在这里插入图片描述

基本语法
循环控制语句,可以用于循环遍历某一序列
else块可选,在循环终止的时候执行,若是break终止循环,else不执行
格式:

for <对象变量> in <对象集合>:
if<条件>:
break
if<条件>:
continue
<其他语句>
else:
<其他语句>

注意:
1.对象集合可以是列表,字典以及元组等
2.for…in循环对于任何序列都适用
3.for遍历一个字典时,遍历的是字典的键
•rang & xrange
可以通过range()函数产生一个整数列表,完成计数循环
range([start,] stop[, step])
start可选参数,起始数
stop终止数,若为x,产生从0-(x-1)的整数列表
step可选参数,步长,未写默认为1
range(1,5) 包含序列为 [1,2,3,4]
xrange和range区别
(python3.x的可无视)

在Range的方法中,它会生成一个list的对象,但是在XRange中,它生成的却是一个xrange的对象,当返回的东西不是很大的时候,或者在一个循环里,基本上都是从头查到底的情况下,这两个方法的效率差不多。但是,当返回的东西很大,或者循环中常常会被Break出来的话,还是建议使用XRange,这样既省空间,又会提高效率。

>>> print range(1, 5)
[1, 2, 3, 4]
>>> print xrange(1, 5)
xrange(1, 5)

在上面语句中,range返回了一个普通List,而xrange返回了一个特定的xrange类型的对象。由于 xrange 方法也创建整数 list(其使用相同参数),所以它与 range 方法非常相似。但是,xrange 方法仅在需要时才在 list 中创建整数。当需要迭代大量整数时,xrange 方法更适用,因为它不会创建*大的 list,那样会消耗大量计算机内存。
while
与if语句类似,含一个条件测试语句,循环,允许重复执行一个语句块。

可选else语句块,同for的else块。

格式:

while <条件>:
if <条件>:
break
if <条件>:
continue
<其他语句>
else:
<语句>

说明:

•while循环条件变为False的时候,else块才被执行
•若是使用break结束循环,while可选的else块不执行
•python没有do while或do until循环语句
break & continue & pass
break,终止循环语句,停止循环,若是for/while循环中终止,其else不执行

continue,结束当前,进入下一轮循环 – 跳到*近所在循环的开头处(来到循环首行)

pass 什么事也不做,只是空占位语句,它用于那些语法上必须要有什么语句,但程序什么也不做的场合

循环else块 :只有循环正常离开时才会执行,即

如果你从for或while循环中break终止 ,任何对应的循环else块将不执行。记住,break语句也可以在for循环中使用

编写循环的技巧
在迭代过程中修改迭代序列不安全(只有在使用链表这样的可变序列时才会有这样的情况)。如果你想要修改你迭代的序列(例如,复制选择项),你可以迭代它的复本。使用切割标识就可以很方便的做到这一点

>>> for x in a[:]: # make a slice copy of the entire list
… if len(x) > 6: a.insert(0, x)

在字典中循环时,关键字和对应的值可以使用 iteritems() 方法同时解读出来

>>> knights = {‘gallahad’: ‘the pure’, ‘robin’: ‘the brave’}
>>> for k, v in knights.iteritems():
… print k, v

gallahad the pure
robin the brave

在序列中循环时,索引位置和对应值可以使用 enumerate() 函数同时得到。

>>> for i, v in enumerate([‘tic’, ‘tac’, ‘toe’]):
… print i, v

DevOps和云计算是什么关系 该如何学好云计算

DevOps和云计算是什么关系?该如何学好云计算?云计算是当前市场上的热门技术,也是未来互联网发展的主要趋势。随着越来越多的企业将业务迁移到云上以及云应用的不断增多,云计算人才成为香饽饽,各大企业纷纷祭出高薪抢夺人才。很多人现在学习云计算时会遇到DevOps,它和云计算究竟是什么关系,接下来就给大家介绍一下。

%title插图%num

DevOps的定义通常分为两个方面:

1)开发和运维之间更友好。在使用这个定义的企业中,IT运维是单独存在的,但是对开发人员来说是非常友好的。例如,DevOps在基础设施的配备中为开发人员提供了自助目录,也为新代码的部署提供了技术支持的通道。

2)DevOps强调独立的综合型团队。在使用这个定义的企业中,开发人员承担运维的责任,反之亦然。

云计算不是一种全新的网络技术,而是一种全新的网络应用概念,云计算的核心概念就是以互联网为中心,在网站上提供快速且安全的云计算服务与数据存储,让每一个使用互联网的人都可以使用网络上的庞大计算资源与数据中心。现阶段所说的云服务是指分布式计算、效用计算、负载均衡、并行计算、网络存储、热备份冗杂和虚拟化等计算机技术混合演进并跃升的结果。

DevOps和云计算的出现是由于社会行为的变化以及对企业响应的相应调整。DevOps是一次高级、快速且不间断的软件程序传输过程,云平台是驱动软件实施敏捷性的性能平台。云计算推动IT转型,通过使用具和自动化技术,帮助企业缩减了工作流程,简化并嵌入DevOps流程,提高了效率,从而实现了真正意义上的变革。这两个功能互为关联,以帮助企业控制开发并利用性能,甚至消除了容易出错的环境。

如果你想成为一个优秀的云计算人才,一定要会借助DevOps的优势。如果你想快速入行UI设计,可以专业学习一下,千万不要错过学习的机会,让自己理论与实战兼备,成为企业急需的高薪精英!

云计算人才必须掌握什么 怎么学Linux性能优化

云计算人才必须掌握什么?怎么学Linux性能优化?Linux是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统,具有免费使用和自由传播的特性。随着开源软件的发展以及云计算技术的革新,Linux成为云计算人才必须要掌握的技能之一。在接下来的分享中,千锋小编就给大家简单介绍一下Linux性能优化之IO子系统。

 

很多同学听过IO流,即以流的方式进行输入输出,其中流是一种抽象的概念,它代表了数据的无结构化传递。IO系统,英文全称为“Input output system”,中文全称为“输入输出系统”,由输入输出控制系统和外围设备两部分组成,是计算机系统的重要组成部分。

%title插图%num

作为Linux服务器来讲,*大的两个IO类型是磁盘IO和网络IO。一个完整的IO系统过程如下:

1)一个用户进程通过write()系统调用发起写请求;

2)内核更新对应的page cache;

3)pdflush内核线程将page cache写入至磁盘中;

4)文件系统层将每一个block buffer存放为一个bio结构体,并向块设备层提交一个写请求;

5)块设备层从上层接受到请求,执行IO调度操作,并将请求放入IO请求队列中;

6)设备驱动(如SCSI或其他设备驱动)完成写操作;

7)磁盘设备固件执行对应的硬件操作,如磁盘的旋转、寻道等,数据被写入到磁盘扇区中。

block layer处理bio请求,并将这些请求链接成一个队列,称作IO请求队列,这个连接的操作就称作IO调度(也叫IO elevator即电梯算法)。bio结构体是file system layer到block layer的接口。

IO调度器的总体目标是减少磁盘的寻道时间(因此调度器都是针对机械硬盘进行优化的),IO调度器通过两种方式来减少磁盘寻道:合并和排序。

合并即当两个或多个IO请求的是相邻的磁盘扇区,通过合并请求,多个IO请求只需要向磁盘发送一个请求指令,减少了磁盘的开销。

排序就是将不能合并的IO请求,根据请求磁盘扇区的顺序,在请求队列中进行排序,使得磁头可以按照磁盘的旋转顺序的完成IO操作,可以减小磁盘的寻道次数。

想要优化IO系统性能,我们可以采用以下几种方式:

1)调整buffer、提高性能,就是调整队列数以及增加预读数。

增加队列长度:/sys/block/vda(特定某设备)/queue/nr_requests

增加预读数:/sys/block/vda(特定某设备)/queue/read_ahead_kb

2)修改CFQ,以调节其性能,涉及参数文件:/sys/block/vda/queue/iosched/。

比如对CFQ来讲,有以下几个值可以调整:

back_seek_max

反向寻道可能有负面影响,负载小的时候可以启用,否则不要使用反向寻道太多值。

back_seek_penal

反向寻道做惩罚,如果不得不使用反向寻道的话,那么必须对其做出一定惩罚,一旦做完惩罚之后,必须要正向寻道更多次数。

fifo_expire_async

用来控制异步请求等待时间长度,默认是250毫秒,过期之后无法满足的异步请求将会被移动到调度队列中,也就意味着要重新调度,通常这些值不需要调整。

除了以上方法,IO优化的方法还有很多,大致思路是*好换SSD、调整raid级别、选择IO调度器、根据场景选择合适的文件系统、配置选定调度器的参数、使用工具进行分析优化结果是否理想、写在开机启动项里。

想了解更多Linux性能优化技巧或者快速入门云计算,你可以选择专业学习一下。让自己求职起点更高、就业速度更快!

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