PyCon大会Python主题演讲摘要

PyCon 是全国际最大的以 Python 编程言语 为主题的技能大会。大会由 Python 社区组织,每年举行一次。在大会上,来自国际各地的 Python 用户与中心开发者齐聚一堂,共同同享 Python 国际的新鲜事、Python 言语的应用案例、运用技巧等等内容。

Instagram 简介

<p "="">Instagram 是一款移动端的照片与视频同享软件,由 Kevin Systrom 和 Mike Krieger 在 2010 年创办。Instagram 在发布后开端快速流行。于 2012 年被 Facebook 以 10 亿美元的价格收买。而其时 Instagram 的员工仅有区区 13 名。<p "="">如今,Instagram 的总注册用户到达 30 亿,月活用户超越 7 亿 (作为对比,微信最新披露的月活泼用户为 9.38 亿)。而令人吃惊的是,这么高的拜访量背后,竟彻底是由以速度慢著称的 Python + Django 支撑。<p "="">在 Python 2017 上,Instagram 的工程师们带来了一个有关 Python 在 Instagram 的主题演讲,一起还同享了 Instagram 怎么将整个项目运转环境晋级到 Python 3 的故事。<p "="">本文为该次演讲的内容摘要。

Python @Instagram

为什么挑选 Python 和 Django

<p "="">Instagram 挑选 Django 的原因很简略,Instagram 的两位创始人 (Kevin Systrom and Mike Krieger) 都是产品经理出身。在他们想要创造 Instagram 时,Django 是他们所知道的最稳定和成熟的技能之一。<p "="">时至今日,即使现已具有超越 30 亿的注册用户。Instagram 依然是 Python 和 Django 的重度运用者。Instagram 的工程师 Hui Ding 说到: 『一直到用户 ID 现已超越了 32bit int 的限额(约为 20 亿),Django 自身依然没有成为咱们的瓶颈地点。』<p "="">不过,除了运用 Django 的原生功用外,Instagram 还对 Django 做了许多定制化作业:<ul "="">

  • 扩展 Django Models 使其支撑 Sharding (一种数据库分片技能),Instagram Engneering 博客专门为这件作业写过一篇博客,可参阅:Sharding & IDs at Instagram
  • 手动关闭 GC(垃圾回收)来提高 Python 内存办理功率,他们相同也写过一篇博客来阐明这件作业:Dismissing Python Garbage Collection at Instagram
  • 在位于不同地理位置的多个数据中心部署整套系统

Python 言语的优势地点

<p "="">Instagram 的联合创始人 Mike Krieger 说过: 『咱们的用户根本不关心 Instagram 运用了哪种联系数据库,他们当然也不关心 Instagram 是用什么编程言语开发的。』<p "="">所以,Python 这种 简略 并且 实用至上 的编程言语终究赢得了 Instagram 的喜爱。他们以为,运用 Python 这种简略的言语有助于刻画 Instagram 的工程师文明,那就是:<ol "="">

  • 专心于定位问题、处理问题 - 而不是东西自身的各种花花绿绿的特性
  • 运用那些经过商场验证过的成熟技能计划 - 而不用被东西自身的问题所干扰
  • 用户至上:专心于用户所能看到的新特性,为用户带去价值

<p "="">可是,即使运用 Python 言语有这么多优点,它仍是很慢,不是吗?<p "="">不过,这关于 Instagram 不是问题,由于他们以为:『Instagram 的最大瓶颈在于开发功率,而不是代码的履行功率』<blockquote "="">

At Instagram, our bottleneck is development velocity, not pure code execution.

<p "="">所以,终究的结论是:你彻底能够运用 Python 言语来完结一个超越几十亿用户运用的产品,而根本不用忧虑言语或框架自身的功用瓶颈。

怎么提高运转功率

<p "="">可是,即就是选用了具有诸多优点的 Python 和 Django。在 Instagram 的用户数迅速增长的进程中,功用问题仍是呈现了:效劳器数量的增长率现已慢慢的超越了用户增长率。Instagram 是怎么应对这个问题的呢?<p "="">他们运用了这些手法来缓解功用问题:<ul "="">

  • 开发东西来协助调优:Instagram 开发了许多包括各个层面的东西,来协助他们进行功用调优以及找到功用瓶颈。
  • 运用 C/C++ 来重写部分组件:把那些稳定并且对功用最敏感的组件,运用 C 或 C++ 来重写,比方拜访 memcache 的 library。
  • 运用 Cython:Cython 也是他们用来提高 Python 功率的法宝之一。

<p "="">除了上面这些手法,他们还在探索异步 IO 以及新的 Python Runtime 所能带来的功用可能性。

晋级到 Python 3

<p "="">在相当长的一段时间,Instagram 都跑在 Python 2.7 + Django 1.3 的组合之上。在这个现已落后社区许多年的环境上,他们的工程师们还打了十分十分多的小 patch。难道他们要被永久卡在这个版别上吗?<p "="">所以,在经过一系列的评论后,他们终究做出一个重大的决议:晋级到 Python 3!!<p "="">事实上,Instagram 现在现已完结了将运转环境搬迁到 Python 3 的作业 - 他们的整套效劳现已在 Python 3 上跑了好几个月了。那么他们是怎么做到的呢?接下来就是由 Instagram 工程师 Lisa guo 带来的 Instagram 怎么搬迁到 Python 3 的故事。

Instagram 晋级到 Python 3 的故事

为什么要晋级到 Python 3

<p "="">关于 Instagram 来说,下面这些因素是推动他们将运转环境搬迁到 Python 3 的主要原因:

1. 新特性:类型注解 Type Annotations

<p "="">看看下面这段代码:

def compose_from_max_id(max_id): '''@param str max_id''' 

<p "="">图中函数的 max_id 参数究竟是什么类型呢?int?tuple?或是 list? 等等,函数文档里边说它是 str 类型。<p "="">但随着时间推移,万一这个参数的类型发作改变了呢?假如某位大意的工程师修正代码的一起忘了更新文档,那就会给函数的运用者带来很大麻烦,终究还不如没有注释呢。

2. 功用

<p "="">Instagram 的整个 Django Stack 都跑在 uwsgi 之上,全部运用了同步的网络 IO。这意味着同一个 uwsgi 进程在同一时间只能接收并处理一个恳求。这让怎么调优每台机器上应该运转的 uwsgi 进程数成了一个麻烦事:<p "="">为了更好使用 CPU,运用更多的进程数?但那样会消耗许多的内存。而过少的进程数量又会导致 CPU 不能被充分使用。<p "="">为此,他们决议跳过 Python 2 中哪些糟糕的异步 IO 完结 (不幸的 gevent、tornado、twisted 众),直接晋级到 Python 3,去探索规范库中的 asyncio 模块所能带来的可能性。

3. 社区

<p "="">由于 Python 社区现已中止了对 Python 2 的支撑。假如把整个运转环境晋级到 Python 3,Instagram 的工程师们就能和 Python 社区走的更近,能够更好的把他们的作业回馈给社区。

断定搬迁计划

<p "="">在 Instagram,进行 Python 3 的搬迁需求有必要满意两个前提条件:<ol "="">

  • 不停机,不能有任何的效劳因而不可用
  • 不能影响产品新特性的开发

<p "="">可是,在 Instagram 的开发环境中,要满意上面这两点来完结搬迁到 Python 3.6 这种巨大的工程是十分困难的。

根据主分支的开发流程

<p "="">即使运用了以多分支功用著称的 git,Instagram 一切的开发作业都是主要在 master 分支上进行的,Instagram 所奉行的开发哲学是:『不管是多大的新特性或代码重构,都应该拆解成较小的 Commit 来进行。』<p "="">那些被兼并进 master 分支的代码,都将在一个小时内被发布到线上环境。而这样的发布进程每天将会发作上百次。在这么频频的发布频率下,怎么在满意之前的那两个前提下来完结搬迁变得特别困难。

被弃用的搬迁计划

<p "="">创立一个新分支<p "="">许多人在处理这类问题时,榜首个蹦进脑子的主意就是: 『让咱们创立一个分支,当咱们开发完后,再把分支兼并进来』<p "="">但在 Instagram 这么高的迭代频率上,运用一个独立分支并不是好主意:<ol "="">

  • Instagram 的 Codebase 每天都在频频更新,在开发 Python 3 分支的进程中,让新分支与现有 master 分支坚持同步开支极大,一起极易犯错
  • 终究将 Python 3 分支这个改动十分多的分支兼并回 Master 具有十分高的风险
  • 只需少量几个工程师在 Python 3 分支上专职担任晋级作业,其他想协助搬迁作业的工程师无法参与进来

<p "="">挨个替换接口<p "="">还有一个计划就是,挨个替换 Instagram 的 API 接口。可是 Instagram 的不同接口同享着许多通用模块。这个计划要施行起来也十分困难。<p "="">微效劳<p "="">还有一个计划就是将 Instagram 改造成微效劳架构。经过将那些通用模块重写成 Python 3 版别的微效劳来一步步完结搬迁作业。<p "="">可是这个计划需求重新组织海量的代码。一起,当发作在进程内的函数调用变成 RPC 后 ,整个站点的推迟会变大。此外,更多的微效劳也会引进更高的部署杂乱度。<p "="">所以,已然 Instagram 的开发哲学是:小步前进,快速迭代。他们终究决议的计划是:一步一步来,终究让 master 分支上的代码一起兼容 Python 2 和 Python 3 。

开端搬迁作业

<p "="">已然要让整个 codebase 一起兼容 Python 2 和 Python 3,那么首先要契合这点的就是那些被许多运用的第三方 package。针对第三方 package,Instagram 做到了下面几点:<ul "="">

  • 拒绝引进一切不兼容 Python 3 的新 package
  • 去掉一切不再运用的 package
  • 替换那些不兼容 Python 3 的 package

<p "="">在代码的搬迁进程中,他们运用了东西 modernize 来协助他们。<p "="">运用 modernize 时,有一个小技巧:每次修复多个文件的一个兼容问题,而不是一下修复一个文件中的多个兼容问题。 这样能够让 Code Review 进程简略许多,由于 Reviewer 每次只需求关注一个问题。

运用单元测试来协助搬迁

<p "="">关于 Python 这种灵活性极强的动态言语来说,除了真实去履行代码外,几乎没有其他比较好的查看代码错误的手法。<p "="">前面提到,Instagram 一切被兼并到 master 的代码提交会在一个小时内上线到线上环境,但这不是没有前提条件的。在上线前,一切的提交都需求经过不计其数个单元测试。<p "="">所以,他们开端参加 Python 3 来履行一切的单元测试。一开端,只需极少量的单元测试能够在 Python 3 环境下经过,但随着 Instagram 的工程师们不断的修复那些失败的单元测试,终究一切的单元测试都能够在 Python 3 环境下成功履行。

单元测试的局限性

<p "="">可是,单元测试也是有局限性的:<ul "="">

  • Instagram 的单元测试没有做到 100% 的代码覆盖率
  • 许多第三方模块都运用了 mock 技能,而 mock 的行为与真实的线上效劳可能会有所不同

<p "="">所以,当一切的单元测试都被修复后,他们开端在线上正式运用 Python 3 来运转效劳。<p "="">这个进程并不是一蹴而就的。首先,一切的 Instagram 工程师开端拜访到这些运用 Python 3 来履行的新效劳,然后是 Facebook 的一切雇员,随后是 0.1%、20% 的用户,终究 Python 3 覆盖到了一切的 Instagram 用户。

图:按部就班的发布流程

搬迁进程的技能问题

<p "="">Instagram 在搬迁到 Python 3 时碰到许多问题,下面是最典型的几个:

Unicode 相关的字符串问题

<p "="">Python 3 相比 Python 2 最大的改动之一,就是在言语内部 咨询入库对 unicode 的处理。<p "="">在 Python 2 中,文本类型 (也就是 unicode) 和二进制类型 (也就是 str) 的边界十分模糊。许多函数的参数既能够是文本,也能够是二进制。可是在 Python 3 中,文本类型和二进制类型的字符串被彻底的区分开了。<p "="">所以,下面这段在 Python 2 下能够正常运转的代码在 Python 3 下就会报错:

mymac = hmac.new('abc')
TypeError: key: expected bytes or bytearray, but got 'str' 

<p "="">处理办法其实很简略,只需加上判别:假如 value 是文本类型,就将其转换为二进制。如下所示:

value = 'abc' if isinstance(value, six.text_type):value = value.encode(encoding='utf-8')
mymac = hmac.new(value)

可是,在整个代码库中,像上面这样的状况十分多。作为开发人员,假如需求在调用每个函数时都要想想: 这里到底是应该编码成二进制,或者是解码成文本呢? 将会是十分大的负担。

<p "="">所以 Instagram 封装了一些名为 ensure_str()、ensure_binary()、ensure_text() 的协助函数,开发人员只需对那些不断定类型的字符串,运用这些协助函数先做一次转换就好。

mymac = hmac.new(ensure_binary('abc'))

不同 Python 版别的 pickle 差异

<p "="">Instagram 的代码中许多运用了 pickle。比方用它序列化某个目标,然后将其存储在 memcache 中。如下面的代码所示:

memcache_data = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
data = pickle.loads(memcache_data)

问题在于,Python 2 与 Python 3 的 pickle 模块是有不同的。

<p "="">假如上文的榜首行代码,刚好是由 Python 3 运转的效劳进行序列化后存入 memcache。而反序列化的进程却是由 Python 2 进行,那代码运转时就会呈现下面的错误:

ValueError: unsupported pickle protocol: 4 

<p "="">这是由于在 Python 3 中,pickle.HIGHEST_PROTOCOL 的值为 4,而 Python 2 中的的 pickle 最高支撑的版别号却是 2。那么怎么处理这个问题呢?<p "="">Instagram 终究挑选让 Python 2 和 Python 3 运用彻底不同的 namespace 来拜访 memcache。经过将二者的数据读写彻底隔开来处理这个问题。

迭代器

<p "="">在 Python 3 中,许多内置函数被修正成了只返成迭代器 Iterator:

map()
filter()
dict.items()

迭代器有诸多优点,最大的优点就是,运用迭代器不需求一次性分配许多内存,所以它的内存功率比较高。

<p "="">可是迭代器有一个天然的特点,当你对某个迭代器做了一次迭代,拜访完它的内容后,就无法再次拜访那些内容了。迭代器中的一切内容都只能被拜访一次。<p "="">在 Instagram 的 Python 3 搬迁进程中,就由于迭代器的这个特性被坑了一次,看看下面这段代码:

CYTHON_SOURCES = [a.pyx, b.pyx, c.pyx]
builds = map(BuildProcess, CYTHON_SOURCES) while any(not build.done() for build in builds):pending = [build for build in builds if not build.started()]

<p "="">这段代码的用处是挨个编译 Cython 源文件。当他们把运转环境切换到 Python 3 后,一个古怪的问题呈现了:CYTHON_SOURCES 中的榜首个文件永久都被跳过了编译。为什么呢?<p "="">这都是迭代器的锅。在 Python 3 中,map() 函数不再回来整个 list,而是回来一个迭代器。<p "="">所以,当第二行代码生成 builds 这个迭代器后,第三行代码的 while 循环迭代了 builds,刚好取出了榜首个元素。所以之后的 pending 目标便里边永久少了那榜首个元素。<p "="">这个问题处理起来也挺简略的,你只需手动的吧 builds 转换成 list 就能够了:

builds = list(map(BuildProcess, CYTHON_SOURCES))

<p "="">可是这类 bug 十分难定位到。假如用户的 feeds 里边永久少了那最新的榜首条,用户很少会注意到。

字典的次序

<p "="">看看下面这段代码:

>>> testdict = {'a': 1, 'b': 2, 'c': 3} >>> json.dumps(testdict)

<p "="">它会输出什么成果呢?

# Python2 '{"a": 1, "c": 3, "b": 2}' # Python 3.5.1 '{"c": 3, "b": 2, "a": 1}' # or '{"c": 3, "a": 1, "b": 2}' # Python 3.6 '{"a": 1, "b": 2, "c": 3}' 

<p "="">在不同的 Python 版别下,这个 json dumps 的成果是彻底不一样的。甚至在 3.5.1 中,它会彻底随机的回来两个不同的成果。Instagram 有一段判别装备文件是否发作改变的模块,就是由于这个原因出了问题。<p "="">这个问题的处理办法是,在调用 json.dumps 传入 sort_keys=True 参数:

>>> json.dumps(testdict, sort_keys=True) '{"a": 1, "b": 2, "c": 3}' 

搬迁到 Python 3.6 后的功用提高

<p "="">当 Instagram 处理了这些奇古怪怪的版别差异问题后,还有一个巨大的谜题困扰着他们:功用问题。<p "="">在 Instagram,他们运用两个主要指标来衡量他们的效劳功用:<ul "="">

  • 每次恳求发生的 CPU 指令数(越低越好)
  • 每秒能够处理的恳求数(越高越好)

<p "="">所以,当一切的搬迁作业完结后,他们十分惊喜的发现:榜首个功用指标,每次恳求发生的 CPU 指令数居然足足下降了 12% !!!<p "="">可是,按理说第二个指标 - 每秒恳求数也应该获得挨近 12% 的提高。不过最后的改变却是 0%。究竟是出了什么问题呢?<p "="">他们终究定位到,是由于不同 Python 版别下的内存优化装备不同,导致 CPU 指令数下降带来的功用提高被抵消了。那为什么不同 Python 版别下的内存优化装备会不一样呢?<p "="">这是他们用来查看 uwsgi 装备的代码:

if uwsgi.opt.get('optimize_mem', None) == 'True':optimize_mem()

注意到那段 ... ... == 'True' 了吗?在 Python 3 中,这个条件判别总是不会被满意。问题就在于 unicode。在将代码中的 'True' 换成 b'True'(也就是将文本类型换成二进制,这种判别在 Python 2 中彻底不区分的)后,问题处理了。

<p "="">所以,终究由于加上了一个小小的字母 'b',程序的整体功用提高了 12%。

结论

<p "="">在今年二月份,Instagram 的后端代码的运转环境彻底切换到了 Python 3 下: 

图:Instagram 版别搬迁时间线

<p "="">当一切的代码都都搬迁到 Python 3 运转环境后:<ul "="">

  • 节省了 12% 的整体 CPU 运用率(Django/uwsgi)
  • 节省了 30% 的内存运用(celery)

<p "="">一起,在整个搬迁期间,Instagram 的月活用户阅历了从 4 亿到 6亿 的巨大增长。产品也发布了评论过滤、直播等十分多新功用。<p "="">那么,那几个最开端驱动他们搬迁到 Python 3 的意图呢?<ul "="">

  • 类型注解:Instagram 的整个 codebase 里现已有 2% 的代码增加上了类型注解,一起他们还开发了一些东西来辅佐开发者增加类型提示
  • asyncio:他们在单个接口中使用 asynio 平行的去做多件作业,终究降低了 20-30% 的恳求推迟。
  • 社区:他们与 Intel 的工程师联合,协助他们更好的对 CPU 使用率进行调优。一起还开发了许多新的东西,协助他们进行功用调优

Instagram 带给咱们的启示

<p "="">Instagram 的演讲视频时间不长,可是内容很丰富,在编写此文前,我彻底没有想到终究的文章会这么长。<p "="">那么,Instagram 的视频能够给咱们哪些启示呢?<ul "="">

  • Python + Django 的组合彻底能够负载用户数以 10 亿记的效劳,假如你正准备开端一个项目,放心运用 Python 吧!
  • 完善的单元测试关于杂乱项目是十分有必要的。假如没有那『不计其数的单元测试』。很难幻想 Instagram 的搬迁项目能够成功进行下去。
  • 开发者和同事也是你的产品用户,使用好他们。用他们为你的新特性发布前多一道测试。
  • 彻底根据主分支的开发流程,能够给你更快的迭代速度。前提是具有完善的单元测试和继续部署流程。
  • Python 3 是大势所趋,假如你正准备开端一个新项目,无需踌躇,拥抱 Python 3 吧!

<p "="">好了,就到这儿吧。Happy Hacking!

 

转载于:https://www.cnblogs.com/blogst/p/10319140.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364072.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

欢迎使用Java 8之前要重温的10个JDK 7功能

Java 8发布已经快一个月了&#xff0c;我敢肯定&#xff0c;大家都在探索JDK 8的新功能。但是&#xff0c;在您完全研究Java 8之前&#xff0c;是时候重新审视Java 7上引入的一些很棒的功能了。记住&#xff0c;Java 6并没有什么功能&#xff0c;它只与JVM的更改和性能有关&…

java版本号管理_微服务项目中如何管理依赖版本号?

本文是微服务项目代码组织形式三部曲中的第三篇&#xff0c;也是最后一篇&#xff0c;通过这三篇文章&#xff0c;相信大家对于如果组织微服务中的代码已经有了一个基本认知&#xff0c;前面两篇分别是&#xff1a;第三篇相对来说要简单一些&#xff0c;本来没打算写&#xff0…

对于刚开始使用该软件,应该在熟悉基本的markdown语法的基础上,再进行快捷键的使用!...

一级标题 # 空格 编写内容 二级标题 ## 空格 编写内容 有序内容 1.Tab 无序内容 -Tab 代码块 print("hello wrold") typora快捷键 ctrl1一级标题 添加图片 表格 CtrlT 姓名年龄职业谢国宏20IT文字加粗 24期的小伙伴们你们好 文字斜体 你好 又粗又斜 粗斜* 3**2 -- 幂…

struct和byte[]相互转换(用Marshal类实现)

转自[DotNet笔记]相当于序列化与反序列化&#xff0c;但是不用借助外部文件1、struct转换为byte[] 1staticbyte[] StructToBytes(objectstructObj) 2{ 3 int size Marshal.SizeOf(structObj); 4 IntPtr buffer Marshal.AllocHGlobal(size); 5 …

Get-CrmSetting返回Unable to connect to the remote server的解决办法

摘要: 微软动态CRM专家罗勇 &#xff0c;回复302或者20190125可方便获取本文&#xff0c;同时可以在第一间得到我发布的最新博文信息&#xff0c;follow me&#xff01;我的网站是 www.luoyong.me 。 在Dynamics 365部署管理器所在的服务器上执行Get-CrmSetting&#xff0c;最近…

java 二维数组奇数金字塔_二维数组:奇数阶魔方 | 新思维:C语言程序设计

幻方&#xff0c;有时又称魔方&#xff0c;由一组排放在正方形中的整数组成&#xff0c;其每行、每列以及两条对角线上的数之和均相等。通常幻方由从到的连续整数组成。Siamese方法(Kraitchik 1942年&#xff0c;pp. 148-149)是构造奇数阶幻方的一种方法&#xff0c;说明如下&a…

拷贝构造函数与赋值函数(运算符重载)(1)

拷贝构造函数拷贝构造函数在三种情况下会被使用1.使用对象来初始化对象时2.当函数的形参是对象时3.当函数的返回值为对象时 2,3情况的本质还是1 //Test1.h #include<iostream> using namespace std; class ST { private:int a;long b; public:ST(int a0, long b0):a(a),…

GOOGLE不让我访问啦?

GOOGLE不让我访问啦? 今天上GOOGLE出现了这么一个画面,可是我就是不知道我的电脑到底中了什么毒,平常我没上什么特殊的网站,也没下载什么软件,因为这电脑我只用来做些基本的开发和看看园子里的文章而已.真不知道是怎么一回事.posted on 2007-05-05 12:46 黄尚 阅读(...) 评论(…

java条件执行方法_java 开启多线程里面如何加条件判断执行其他逻辑?

方法1&#xff1a;通过Thread类中的isAlive()方法判断线程是否处于活动状态。线程启动后&#xff0c;只要没有运行完毕&#xff0c;都会返回true。【注】如果只是要等其他线程运行结束之后再继续操作&#xff0c;可以执行t.join()&#xff0c;即&#xff1a;在t执行完毕前挂起。…

大数据分析和人工智能科普

一、大数据 1.1 大数据&#xff08;Big Data&#xff09; 众说纷纭&#xff01; 个人认为&#xff0c;大数据中的“大”&#xff0c;不仅仅是涉及数据规模&#xff0c;而且包含“价值“这个层面。其实无非就是大量的信息罢了&#xff0c;但是我们却能 通过各种手段从这些信息中…

Redis API的使用与理解

一、Redis 基础&#xff1a; 1、通用命令&#xff1a; keys [pattern]&#xff1a; keys * #遍历所有key&#xff1b;keys he* #以he开头的key&#xff1b; keys he[a-e]* #以‘he’开头第三个字母是a-e之间&#xff1b; keys ph? #?代码一位&#xff0c;以ph开头且字母是…

点击底部input输入框,弹出的软键盘挡住input(苹果手机使用第三方输入法 )

测试移动端页面的时候&#xff0c;偶然发现点击底部input输入框时&#xff0c;弹出的虚拟键盘偶尔会挡住input输入框。 输入框固定在页面底部&#xff0c;如图所示&#xff1a; input固定底部设计图.png点击底部input输入框唤起软键盘时&#xff0c;软键盘挡住输入框。如图所示…

java采集温湿度水浸_机房水浸传感器:智能生活不可或缺的漏水传感器

原标题&#xff1a;机房水浸传感器&#xff1a;智能生活不可或缺的漏水传感器智能化的飞速发展让人们的生活发生了重大改变&#xff0c;为保证机房的安全、稳定、高效运行&#xff0c;网络设备的良好运行状态和设备使用寿命与安全&#xff0c;通常会对网络运行环境的电力供应、…

创建型模式:原型模式

个人公众号原文&#xff1a;创建型模式&#xff1a;原型模式 五大创建型模式之五&#xff1a;原型模式。 简介 姓名 &#xff1a;原型模式 英文名 &#xff1a;Prototype Pattern 价值观 &#xff1a;效率第一 个人介绍 &#xff1a; Specify the kinds of objects to create u…

我的前端工具集(五)提示工具之模态窗提示

我的前端工具集&#xff08;五&#xff09;提示工具之模态窗提示 liuyuhang原创&#xff0c;未经允许禁止转载 目录 我的前端工具集 1、需求 很多页面操作都需要提示&#xff0c;比如操作成功&#xff0c;操作失败之类。 总不能没事就console.log或者alert吧。 所以一个操作提…

Java 8 Friday:可选将保留为Java中的一个选项

在Data Geekery &#xff0c;我们喜欢Java。 而且&#xff0c;由于我们真的很喜欢jOOQ的流畅的API和查询DSL &#xff0c;我们对Java 8将为我们的生态系统带来什么感到非常兴奋。 Java 8星期五 每个星期五&#xff0c;我们都会向您展示一些不错的教程风格的Java 8新功能&#…

七天开发记录(3)

今天在网上找到了一个开发记账本微信小程序的网址 我看了一下这个APP的源代码&#xff0c;其用分为两个大包。 转载于:https://www.cnblogs.com/zjl-0217/p/10428525.html

TMS320F28335——IO控制/定时计操作

一、实现GPIO控制 1.硬件连接 从电路原理图上看来&#xff0c;LED灯是接在GPIO34 上的。 2.IO设置 2.1设置功能 GPXMUX1/2&#xff1a;功能选择寄存器   GPXMUX1/2 每组 IO 一般有 32 个 IO 口可以配置。GPXMUX1 对应每组的低 16 个 IO 口&#xff0c;GPXMUX2 对应高 16 个…

比Python、Java更快的 Go 语言,能否称霸江湖?

关注之后加星标&#xff0c;江湖要事早知道 ​ 文章来源&#xff1a;jb51.net 有一种语言堪称比语言排行榜前五热门选手的Python、Java更快&#xff0c;它就是GO语言。 Go于2009年11月正式宣布推出&#xff0c;成为开放源代码项目&#xff0c;并在Linux及Mac OS X平台上进行了实…

嗨,您好 。 。 ! 您如何评价Java / Java EE技能?

要知道&#xff0c;就是要知道你一无所知。 那就是真正知识的含义。 苏格拉底 这篇文章旨在为读者提供Java生态系统及其技术堆栈的快速概述。 老实说&#xff0c;从Java EE 7&#xff0c;Java SE 8到Java Embedded 8…&#xff0c;Java平台进行了许多革命性的更改和添加。 哇…