使用Prettier,Husky和lint-staged,在提交javascript代码前自动格式化代码

目标

为防止提交不合格的代码排版到仓库中,我们希望在提交前格式化代码,使之符合项目的代码格式规范,而且尽可能保证逻辑正确。即目标有两点:
1. 对git staged的代码强行格式化,使符合规范。对于没有被staged的代码或文件,将完全忽略。
2. 跑单元测试。只有通过了单元测试才能提交代码。

安装依赖

$ npm install --save-dev husky lint-staged

先安装husky和lint-staged。注间在安装husky之前需要确保工程目录已经是一个合法的git仓库。因为,安装husky时需要给git仓库安装预提交钩子(precommit hook)。
Lint-staged提供了一个关键的功能,它能找到所有被git staged的文件,而不是工程下面所有的文件,然后通过管道交给Prettier做格式化。

修改npm脚本

对npm script做如下改动:

  "scripts": {
    "precommit": "lint-staged"
  },
  "lint-staged": {
    "*.{js,jsx,json}": ["prettier --write", "git add"]
  }

scripts.precommit由Husky处理,它会依照配置在把代码正式提交到仓库前运行lint-staged(当然我们也可以配置其他命令)。
Lint-staged再找到属于它自己的配置部分,即lint-staged键下面的配置。
在此例中,所有staged状态的,且扩展名是.js, .jsx, 和.json文件都会自动交由Prettier做格式化,然后再提交。

为何一定要用lint-staged

You might wonder why we don’t just use Husky to run a few npm scripts.
你可以会疑惑,为什么一定要罗里罗嗦地用lint-staged,用Husky直接调用npm脚本不更简单么。
这是因为我们用lint-staged拿到staged状态的文件,而不是所有的文件。
你的node工程文件中可能已经有如下做代码格式化的脚本

"format": "prettier --write '**/*.{js,jsx}'"

你可能会因此如下配置

"lint-staged": {
  "*.{js,jsx,json}": ["npm run format", "git add"]
}

如果是这样配置的话,就没有必要用lint-staged了。因为,这样的配置会把prettier应用到所有匹配.js,.jsx.json的文件上,而不是仅staged状态的文件。

把跑单元测试加入预提交检查

Husky还能够帮你把跑单元测试加入到预提交检查中,保证只有通过了单元测试才正式提交代码到仓库。
如下是一个典型的配置:

"scripts": {
    "test": "exit 0",
    "precommit": "lint-staged && npm test"
  },
  "lint-staged": {
    "*.{js,jsx,json}": ["prettier --write", "git add"]
  }

实际项目中要修改scripts.test部分,视工程使用的单元测试框架Jest, 或Mocha ,本示例简单的返回0,表示无条件通过。

python用multiprocessing起子进程,父进程被杀掉时,如何让子进程也自动退出

最近用python3写了一段代码,代码会起一个子进程做一些辅助的事情。但发现父进程被杀死后,这个子进程变成了孤儿进程,仍然在运行。
起进程的代码大概如下:

from multiprocessing import Process, Queue    
__q = Queue() 
__p = Process(target=__run, args=(__q,))                                                                                                           
__p.start()   

很不方便,那怎样让父进程退出后,子进程也跟着退出呢。
一番google之后,原来可以用一行代码解决:

from multiprocessing import Process, Queue    
__q = Queue() 
__p = Process(target=__run, args=(__q,))   
__p.daemon = True    # 加上这一行代码
__p.start()   

设置子进程的daemon属性为True。这样,当在控制台上用ctrl-c,退发送SIGTERM杀掉父进程后,子进程也会跟着退出,不会成为孤儿进程。
参考python官方的解释:

daemon
The process’s daemon flag, a Boolean value. This must be set before start() is called.
The initial value is inherited from the creating process.
When a process exits, it attempts to terminate all of its daemonic child processes.

官方解释的重点是daemon flag必须在start()前被设置。
还有一个坑人的地方,貌似父进程必须被SIGTERM信号杀死,或者自行自然退出,子进程才会退出,否则还是变成了孤儿进程。在stackoverflow上有人提到了这点:
https://stackoverflow.com/questions/25542110/kill-child-process-if-parent-is-killed-in-python

I want to mention, that if parent process was killed using SIGKILL (kill -9) then daemon processes won’t stop.

我想,这或许应该是由于-9(SIGKILL)会立刻中止父进程,于是父进程没有机会通知子进程,比如用atexit设置的进程退出时调用的hook函数就没机会执行了。

Rust中的&str和String有什么区别

&str和String让Rust初学者困惑不已。这里简单的介绍一个&str和String的区别。

String就像是Vec一样是动态分配在堆heap上的字符串类型,它指向一串UTF8编码的字节序。当需要拥有该字符串,要更改字符串的内容,要把字符串在线程之间传递,要在运行时动态创建字符串时使用此类型。

str也指向一串UTF8编码的字节序,但并不拥有指向的字符串,而仅仅只是一个“string slice”。slice的详细解释点链接。str绝大多数情况下以引用&str的形式出现。又被称为字符串字面值(string literal)。
和String指向的字符串肯定分配在堆上面不一样,str指向的字符串可能出现在各种地方:
1. 在程序的全局静态空间(.text段??)。一个string literal的类型和生命期是:&’static str。字符串的数据硬编码进生成的程序或库文件,但程序加运行时,字符串加载进内存。
2. 分配在堆上面 String有一个方法是as_str,它返回一个&str,指向String管理的堆上面的字符串。另外,String有实现Deref<Target=str>这样一个Trait,让所有接受&str作为参数的函数,都可以传String的引用。编译器会自动把&String转成&str。
3. 分配在栈上面 如下面的代码,变量stack_str的类型是&str,它指向栈上面的字符串。

use std::str;

let x: &[u8] = &[b'a', b'b', b'c'];
let stack_str: &str = str::from_utf8(x).unwrap();

如果以C++程序员的视角看String和&str。一个Rust的String类似std::string,完全拥有并管理(创建,销毁)需要的内存。而Rust的&str则类似char*(当然实际上要复杂很多),仅仅指向字符串,不负责管理对应的内存。

再看看String和&str的互转化:
&str转String可以用三种方法

    let a: String = "hello rust".into();
    let c: String = "hello rust".to_string();
    let b: String = String::from("hello rust");
    println!("{}", a);   // 都输出 hello rust
    println!("{}", b);
    println!("{}", c);

String转&str可以直接引用String类型的值或者调用String的as_str方法。

let a: String = String::from("hello rust");
let aaa: &str = &a;
let bbb: &str = a.as_str();

转载请注明出处链接 http://blog.ykyi.net/2019/10/rust%E4%B8%AD%E7%9A%84str%E5%92%8Cstring%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB/

linux怎么把一个正在前台运行的进程用nohup放入后台运行

假设进程在控制台运行。
三个步骤:
1. ctrl + z 停止正在运行的进程
2. $ bg 命令把该进程放入后台
3. disown -h [job的序号] 后台的进程有类似%1, %2, %3的序号。

至此,一个正在控制台前台运行进程被放入后台,且忽略SIGHUP信号。这样,即使关闭了控制台,也不会杀死这个进程了。

python自制包并用pip免提交到pypi仅安装到本机

不得不说python的自制包的相关工具真是多且混乱,什么setuptools,什么distutils,什么wheel,什么egg!!怎么有这么多啊??

而且我的需求且且是创建一个自制包管理自己常用的代码,也必不想提交到PyPI,仅仅只需要安装到本机就行。

下面就是几个关键步骤。

  1. 文件目录布局
    ├── package1
    │ └──-├── init.py
    | |── mod1.py
    │ └── mod2.py
    ├── setup.py
    |── README.md
  2. 编写setup.py文件,类似如下:
from setuptools import setup, find_packages

setup(
    name="kamustools",
    version="1.0.1",
    author="Kamuszhou",
    author_email="zausiu@gmail.com",
    description="tools used by kamuszhou exclusively.",
    license="BSD",
    keywords="kamus",
    url="https://blog.ykyi.net",
    packages=find_packages(),
    long_description="Long descrition is actually short...",
    classifiers=[
        "Development Status :: 3 - Alpha", 
        "Topic :: Utilities",
        "License :: OSI Approved :: BSD License",
    ],
)
  1. python3 setup.py sdist bdist_wheel
  2. pip install ./dist/kamustools-1.0.1.tar.gz

就这四步,其他各种功能,以后要用了再慢慢看吧,实在太庞杂了。满足我自己需求的这四个简单步骤就记录在这里。

Wikipedia维基百科为什么不放广告,是因为版权原因吗?

答:不!维基百科不投放广告,不是因为版权原因。

https://en.wikipedia.org/wiki/Wikipedia:Funding_Wikipedia_through_advertisements 维基官方对投放广告的官方解释:17点理由不投放广告,没有一点提到版权。

通篇只有一处提到版权,是创始人Jimmy Wales的一段话:

I believe that if we looked at putting ads into the search results page (only), with the money earmarked for specific purposes (with strong community > input into what those would be, either liberation of copyrights ….
我相信,如果我们把广告放到搜索结果中,由此筹到的钱可用于特殊用途(社区的大量投入将是版权的解放)

有人说:

像这种权威的百科站点,例如莫种性病的解释词条边上出现一个莆田医院的广告,会怎样?难以想象!这种事也就百度做得出来吧。

上面链接中维基官方给出的不放广告的解释中就有几点的意思一致。
1. Ads cheapen the encyclopedia 会让维基掉价;
2. Threat to neutrality of content 影响内容中立;
3. Conflict of interest 和用户利益冲突.
4. Inappropriate ads 广告内容可能不恰当

上面的官方链接还有一条很强的证据能证明维基不放广告和版权无关。

The right to fork. It is inherent in the use of an open license that projects can fork. Thus far the largest fork away from Wikimedia was by a large part of the Spanish Wikipedia community who left because advertising was being considered. 

有权分叉(复制)。这个权利是维基的许可证所允许的。目前最大的分叉是西班牙语维基。他们离开了维基百科,因为他们想要投放广告。

维基百科的官方许可证页面 https://en.wikipedia.org/wiki/Wikipedia:Copyrights
维基百科的绝大多数内容的许可证是 Creative Commons Attribution-ShareAlike 3.0 和 the GNU Free Documentation License (GFDL)
这是两个非常宽松的许可证,意味着你可以随便复制并修改维基百科的内容(图片内容另有规定),商业化也是被允许的,当然包括投放广告。具体的条款,没时间细看了。