使用Docker+VS Code搭建Go+Python的开发环境

因为项目需要,可能使用Go调用Python 3的接口,趁这个机会实践了一下,如何用Docker+VS Code迅速地搭建开发环境,真的非常非常非常香!

准备Docker Image和Container

先使用Docker迅速的Build出包含了Go,Python 3.7的Image,同时也下载了DataDog/go-python3。这是一个挺不错的Go Module,可以用来调用Python 3的C API,进而调用Python的API(后续写篇文章介绍一下用法)。

有了Dockerfile,再使用docker build生成Image

Image生成后,就可以启动Container了,

Container的名字叫go_dev, 同时挂载了H:\go_dev/go_dev上。Container里的go, python3都已经安装完成。

使用VSCode连接到Docker container

首先需要安装Remote Container的插件,真的是个神器!

安装完成后,可以在左下角一个新的张铎图标,点击后就可以连接刚才启动的Container了。

在菜单中选择,“Attach to Running Container

在后面的菜单中,选择Container “go_dev”。第一次连接时,需要选择一个目录来写代码了。连接后,打开Terminal也默认调整在Container里的目录。非常方便!

在Remote模式下,代码的很多分析是在Container里完成的,所以在第一次连接完成后,你需要把一些需要的Plugin再安装一下,比如Go语言的支持,Python的支持等等。这个要根据实际的需要。

好了,开发环境搞定,继续板砖写代码吧!

 

 

A tricky thing in C++ – Will a member function call by using a raw nullptr crash? Maybe no.

As a Java/Python developer for about 10 years, in my mind, invoking a member function from a raw nullptr, there should have always exceptions, as the following shows.

Maybe you think why I discuss about this naive question. Since recently I found, it’s may not be true for C++ and it depends on how the C++ class defines.

Take a look at the following code written by C++ and execution results.

Surprisingly, the code was executed correctly! It’s tested by VC 2019, GCC 4.8.4/7.3.

I never noticed this but after more time thinking, you may understand the reason. It’s because there is no member field de-referenced in C++ class of “A”.

Let me explain it simply. The function A::hello() will be renamed (there is a full set of naming convention) and compiled into a kind of a C function. And the parameter of pointer of “this” will be added into the function (not that simple, but you can understanding like that). So A::hello() will be compiled to a function like _ZN1A5helloEv(A* this). When you call “a->hello()”, actually, it looks like “_ZN1A5helloEv(a)”. Calling a C function will not cause segment fault, but de-referencing will.

The following code snippet will give you better understanding.

In OOP, this kind of class “A” is not useful. No member fields means a object has no properties. For this case, you should use static function and invoking the function as a class function.

But this tricky behavior is good for us to understand how C++ language works.

Use Atlassian Confluence API to Copy and Create New Pages

For team management, we have a Confluence space to do weekly reporting. In that space, usually, one page is for a week and each page has the same template. So to copy these pages becomes a very boring work. No worries, there are Confluence APIs to help.

Installation and Connection to Confluence

Very simple and pip will help to finish everything.

After installation, use the following code to connect to Confluence.

Copy and Create New Page

Before creating new page, you need to get the body content of the template page.

Pay attention to the expand=’body.storage’. Without it, the returned page only contains the basic information, no body HTML.

Now you have the body and the rest work is a just for-loop.

Also you can use confluence.update_page() to update some existing pages.

References

Create Python Virtual Environment with virtualenv

There are a lot of pros to using a virtual environment to manage different Python environment, which will be independent of each other. The following are the steps to create one under Ubuntu 16.04 with Python 2.7.x

Install the virtualenv with the necessary packages

Create a folder for the virtualenv

Activate & Deactivate the virtual environment

After sourcing the activate script, you can find a “(myenv)” in front of the folder prompt, which is the virtual environment’s name and it has been activated.

Now, the pip can be used to install/update the python modules belongs to this virtual env only.

To deactivate is also very simple.

 

对Python脚本做简单的profiling

最近事情好多,Blog好久没有更新了。今天上来写写最近解决的一个Python里的性能优化问题。

起因

之前为项目写过一个Sqlite数据库预处理的Python脚本,里面主要做了张新表,把其他表的数据填进去。当时主要考虑到维护性,条理清楚,就没太考虑Performance。之后QA发现模块的运行比原来慢了20倍,因为还是挺快,所以没有当时马上修正。

Profiling

这次Release要修掉这个问题。我的原则是,改进Performance一定要做Profiling,做到有的放矢才。

和Java的VirtualVM类似,Python 2.7也内置了几个Module做Profiling,我选择了cProfile。基本就是如下命令:

“-s tottime”是让结果用总执行时间排序。

优化之前的执行结果,

可见罪魁祸首就是sqlite3的Cursor的execute()方法,和原本猜测的也是一样的。优化的手法也很明确就是减少execute()的调用次数,使用batch和合并SQL语句的办法,很容易就用空间换回了时间。

优化之后的结果,

优化之后只是原来的9%的Runtime。

总结

  • 继续坚持用Profiler来做Performance的改进。
  • 边改边用Profiler查看Performance有没有提升。
  • 不要过分优化,否则代码没法看了。😀

References

强大的XPath

最近的项目开发中常常要分析XML,深切体会到XPath的强大和方便。Java可以使用DOM4j,Python 2.5以后可以使用了etree。

举个小例子,如果有如下XML:

要去掉所有<B>的节点,XPath可以如何做呢?

XPath的灵活之处就在于,可以用简单明了的Path控制想要读取的节点。

其实还有很多有趣的特性,可以看看XPath Tutorial

How to migrate ReviewBoard database from sqlite to MySQL

About 3 years ago, I introduced Review Board into our team with a great help from RB group and replaced CodeStrike. We deployed RB on a WinXP VM and the backend database is sqlite. I can’t remember the reason. Maybe I just wanted to save some time. Actually, it has spent a lot of time of our team.

Why? Because sqlite is a lightweight DB and it have bad performace in concurrency scenario. For our team, we have about 20 developers and RB is the most popular daily tools. Now we have to say, we highly depend it to control the quality of team’s code.

Recently, the dababase issue was getting worse. RB pages can’t be created well and there are many warnings/errors on it. And yesterday, the database was dead finally-“The database is locked!”. That’s a message from Django. I googled and the best solution is to use better database to avoid such issues in future.

I took about 3 hours to migrate database to MySQL 5.1. Maybe my experience can help you to save some time.

Step 1. sqlite bump

Go to sqlite.com and download a command line. For window version, you can find it here.

Unzip it and use command to dump sqlite database.

reviewboard.db is the database file of sqlite.

Step 2. Convert to MySQL dump

Now we have the sqlite dump file. But you can’t import it into a MySQL database directly. Because some syntax is not supported by MySQL.

I googled and got a free converter to do that. You can find it here and download sqlite3_mysql.zip.

In the deep of the zip , you can find a executable file – sqlite_mysql.exe. Run it and convert the sqlite dump file to a MySQL one.

Step 3. Import MySQL dump

Before that, please create a database in your MySQL database.

In my case, the dump is about 180M and I waited very long time. (And there may be some warning messages. I don’t know why but for now the migrated server works well. So maybe we can’t ignore them.)

Step 3.1 Alter database structure

Actually, this issue was found when I finished Step 4 and restarted RB. At the beginning, RB worked well. But a minute later, a guy said he could’t submit any comments.

The root cause was the “id” field of some tables lost the property of “AUTO_INCREMENT”. I didn’t know why and SQL in dump file was right. Then I write a very simple .py script to fix this issue.

I just went through all tables and alter the property of “id” field if the table has one.

Step 4. Change RB configuration file

Change rb_site_root/conf/settings_local.py to:

Make sure MySQLdb is installed or there will be error when restart RB.

The best moment came finally! RB restarted successfully and all review request/comment/diff were there. And the performance was improved. You can feel the page is loaded fast. Cheers! 😀

If you have the same problem with me, I hope this post can help and save some time.

Java技术学习之Class文件

Java Class文件是由Java Compiler编译源文件之后产生的。Class文件里保存的就是大名鼎鼎的ByteCode(字节码)。其实在JVM Specification有对它格式的详细描述,我也因此用Python写了一个解析器PyJavap。昨天这个小工具也到了第一个Milestone,支持1.5以前的规范。我心里还是很有成就感的,同时对ByteCode也有了更深了理解,在我的GitHub上可以找到。

现在对Java技术的兴趣越来越深,继续研究吧! 🙂