
作为一个 Java 为母语的程序员来讲,学习起其他新的语言就难免任何事都与 Java 进行横向对比。Java 7 引入了能省去许多重复代码的
try-with-resources特性,不用每回 try/finally 来释放资源(不便之处有局部变量必须声明在 try 之前,finally 里还要嵌套 try/catch 来处理异常)。比如下面的 Java 代码1try(InputStream inputStream = new FileInputStream("abc.txt")) { 2 System.out.println(inputStream.read()); 3} catch (Exception ex) { 4}它相应的不使用 try-with-resources 语法的代码就是 Read More

上一篇 Python 的模块搜索路径,介绍了 Python 的模块搜索路径,最终起作用的是
sys.path路径列表。如果要自定义自己的搜索路径,就是要怎么定制sys.path的内容。可以简单的用PYTHONPATH环境变量前向添加,这儿将要说的是用.pth文件的方式。也可由此进一步理解 Python 依赖管理工具,像virtualenv等的工作原理。.pth文件名是什么,无所谓,Python 只认扩展名。.pth文件中每行指定一个路径 -- 绝对或相对路径(相对于本.pth文件所在的目录),另外还可以空行或#开始的注释行,还能有import语句,大概只用来校验是否能导入成功,程序代码中还是需要显示的 import 模块。.pth文件放在哪里.pth文件创建好后应该放到哪里去呢?不是sys.prefix指示的位置,也不是sys.path中任意一个目录,而是sys.path中属于 site.packages 的某一个目录中。可以用1>>> import site 2>>> site.getusersitepackages() 3>>> site.getsitepackages()查看到, 看我在 Ubuntu Linux 中看到的内容(为便于阅读,显示列表内容时进行了换行处理) Read More

一种语言要使用到外部库(模块) 时必然会涉及到从哪里以及按何顺序加载依赖,就像 LD_LIBRARY_PATH, CLASSPATH 那样,Python 也有其默认的模块搜索顺序, 依序找到想要的模块即停止。Python 中
sys.path返回的列表包含了模块搜索的顺序,我们可以程序中修改该列表,或用PYTHONPATH环境变量前插路径,甚至是用.pth文件来附加路径。简单的,可以执行命令
python3 -c "import sys; print(str(sys.path).replace(',', '\n'))"来查看 python3 交互 shell 下的模块搜索路径,类似结果如下:[''
'/usr/lib/python36.zip'
'/usr/lib/python3.6'
'/usr/lib/python3.6/lib-dynload'
'/home/yanbin/.local/lib/python3.6/site-packages'
'/usr/local/lib/python3.6/dist-packages'
'/usr/lib/python3/dist-packages'
'/usr/lib/python3.6/dist-packages']注意,第一个元素是个空字符串,代表进入 python3 shell 时的当前目录。
如果在通过一个 py 脚本文件来打印
sys.path的话显示稍微有所差异。比如在目录/home/yanbin/Developers/下创建test.py文件,内容为 Read More
阅读到 Strings 中关于转换对象为字符串的内容,介绍了
repr函数,趁着还没有真正了解 Python 面向对象的生疏与热度,感性上理解一下repr与str这两个函数的区别。Python 的全局方法
repr和str会映射到对象的__repr__和__str__的方法调用,还有str(obj)时会调用哪个方法,以及print(obj)和调试 Python 代码时的对象显示会调用哪个方法呢?这就是本文想要印证的内容。恰如 Java 的
System.out.println(obj)或"hello" + obj都会调用 Java 对象的toString()方法,那么 Python 中是怎么一回事呢?来自某本 Python 入门书的解释
repr和str:repr: formal string representation of a Python objectstr: informal string representation of a Python object,或者说 printable string representation
首先
repr是 representation 的意思,一个是正式,另一个是非正式,看起来repr比str显得重要些。 Read More
Web 程序我还是喜欢用 Apache 来作为入口,因为我用的系统是 Mac OS, Apache 它就静静的躺上那儿了。最好是都像 PHP 那样的程序,无需启动额外的服务,这种使用方式的缺陷是不太适合于做微服务。
这儿呢,我也是来探索如何在 Apache 中运行 Python 的 CGI 程序,这主要是涉及了 Apache 与 Python 的集成。集成方式有直接集成(mod_python),CGI,FastCGI, WSGI 和 uWSGI。本文主要是讲如何运行一个简单的 Python CGI。
直接集成(mod_python)
虽然由于多方面的安全因素,这已经成为历史了,但还是提一下。参见
- Apache HTTP Server/mod_python(它推荐使用 mod_wsgi, 以下该节相关内容摘在本链接,没有亲自尝试)
- mod_python 官网(最后的更新是 2013-11-13)
需要安装模块 mod_python.so,并在
httpd.conf加上相关的配置 Read More
两年前想摸摸 Python 的门道,简要记录了一篇 我的 Python 快速入门,当时只觉得那是一种与 C/Java 异样风格的编程语言,没领会到特别之处。如今对 Python 的感受就不一般了,因为是云服务,机器学习,人工知道大行其道的年代,所以更为急迫的想把它好好弄明白。
Python 3 说是设计的比 Python 2 要合理的多,所以没有保持向后兼容,现在初学 Python 对于选择哪个版本的 Python 时没有任何犹豫了,当然拣最新的 Python 3 学了。因此各种命令行工具都得用有 3 标记的,如
python3,pip3,pydoc3。编程语言特别是脚本语言,简单验证或入门最需要一个
REPL工具,这里不论大型项目时最好选择全功能型的 IDE,像 PyCharm 这样的重型武器。在安装 Python 3 后,它自带了两个,分别是python3和idle3(据说是 Integrated DeveLopment Environment 的缩写词, 可没见这么简陋的 IDE)Python
命令
python3进到控制台的 Python 交互界面,Python 标准的>>>提示符。没有语法高亮,没有自动缩进,唯一高级点的功能就是tab能对变量可以方法,属性的自动完成。 Read More
Kafka 消息的 Producer 在调用
producer.send()方法发送消息时会先把消息放到本地缓冲中,然后由 Kafka 网络线程从缓冲中提取消息再送到 Kafka 代理上去。本地缓冲区大小由buffer.memory来配置,默认为 32M(32 * 1024 * 1024L)。如果发消息到网络慢于提交消息到缓冲区的话,缓冲区就可能会满就无法接受新的消息,这时候就要依照block.on.buffer.full设置是否暂停还是抛出异常,默认为暂停producer.send();暂停时间由max.block.ms决定,默认为 60 秒。producer.send()返回一个Future<RecordMetadata>, 也就是每次调用send()方法在缓冲区满后要等待 60 秒才能获得结果(异常)。这里的关系是
send()--a-->缓冲区--b-->发送到 Kafka 代理,自然要在a与b之间进行流量控制,如果b太慢,缓冲区满的话必须把a放慢下来。如果能基于缓冲区已使用大小来放缓a也是也行的,留待以后进行研究。本文提供另一种实现参考,为 Producer 配置一个Interceptor能够大致统计多少消息提交到缓冲区,多少消息从缓冲区取出。Kafka 的所有配置项常量可以在这个页面 https://kafka.apache.org/0100/javadoc/constant-values.html 找到。对 `interceptor.classes` 的解释是:可以为 Producer 配置一个或多个 Interceptor(需要实现 ProducerInterceptor)。另外 Consumer 也有自己的 Interceptor(实现 ConsumerInterceptor)。 Read More

得益于 Java 8 的 default 方法特性,Java 8 对 Map 增加了不少实用的默认方法,像
getOrDefault,forEach,replace,replaceAll,putIfAbsent,remove(key, value),computeIfPresent,computeIfAbsent,compute和merge方法。另外与 Map 相关的Map.Entry也新加了多个版本的comparingByKey和comparingByValue方法。为达到熟练运用上述除
getOrDefault和forEach外的其他方法,有必要逐一体验一番,如何调用,返回值以及调用后的效果如何。看看每个方法不至于 Java 8 那么多年还总是if(map.containsKey(key))...那样的老套操作。前注:Map 新增方法对 present 的判断是 map.containsKey(key) && map.get(key) != null,简单就是 map.get(key) != null,也就是即使 key 存在,但对应的值为 null 的话也视为 absent。absent 就是 map.get(key) == null。
不同 Map 实现对 key/value 是否能为 null 有不同的约束, HashMap, LinkedHashMap, key 和 value 都可以为 null 值,TreeMap 的 key 为不能为 null, 但 value 可以为 null, 而 Hashtable, ConcurrentMap 则 key 和 value 都不同为 null。一句话 absent/present 的判断是 map.get(key) 是否为 null。
方法介绍的顺序是它们相对于本人的生疏程度而定的。每个方法介绍主要分两部分,参考实现代码与示例代码执行效果。参考实现代码摘自 JDK 官方的 Map JavaDoc。
getOrDefault 方法
本想忽略这个方法的测试,因为涉及到 key 存在,值为 null 的情况。当 key 不存在或相关联的值为 null 时,返回默认值,否则返回实际值。不要认为 key 存在时总是返回 map.get(key) 的值。
参考实现:
Read More
本文记录 SpringBoot 与 Logback 是如何工作的,即观察 SpringBoot 中 Logback 是怎么一步一步初始化的。用以测试的 SpringBoot 版本是 1.5.16, 而非最新的 SpringBoot 2。关于 SpringBoot 日志的官方文档在 Logging, 但不太详细或透彻。本文也不承诺说就理解得更有深度,只是为官方文档提供更多方面的参考。
SpringBoot 默认使用 Slf4J + Logback 来记录日志,对于一个基本的依赖于
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>的 Spring Boot 项目,上面组件依赖了 spring-boot-starter-logging 组件,而该组件又引入了以下几个依赖
- logback-classic: 依赖了 Slf4J
- jcl-over-slf4j
- jul-to-slf4j
- log4j-over-slf4j
相当于把其他的日志框架全桥接到了 Slf4J + Logback 上去了。 Read More

Amazon 在 2018 年 6 月份宣布可以设置用 SQS 来触发 Lambda,SQS 不再是单纯用于 ECS 服务中,或用于伸缩控制的。这儿就来亲自尝试一下用 SQS 驱动的 Lambda,以及要注意的要素。
首先使用 Java 编写 Lambda 的话,AWS 在 com.amazonaws:aws-lambda-java-events:2.20 版本开始加入了 com.amazonaws.services.lambda.runtime.events.SQSEvent 类,可是这个版本的 aws-lambda-java-events 是有所限的,因为
SQSEvent.SQSMessage类是私有的,这就造成不能获取到 SQSEvent 中的记录数据。//下面的操作代码无法编译,因为 SQSEvent.SQSMessage 是私有的,不可访问
SQSEvent.SQSMessage sqs = sqsEvent.getRecords().get(0);
sqsEvent.getRecords().get(0).getBody();Java 使用 SQS 来驱动 Lambda 的话,至少需要 com.amazonaws:aws-lambda-java-events:2.2.1 版本,从此 SQSEvent.SQSMessage 变成 public 了。该版本是于 2018 年 6 月传到 Maven 官方中央仓库的,这就是那时才能真正用来写 Java 的 SQS 触发的 Lambda.
同时此篇也是作为上文 AWS Lambda 重试与死信队列(DLQ) 的一个很重要的补充。在此也会验证 SQS 触发的 Lambda 的重试机制以及 DLQ 相关的内容。 Read More