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_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)
这是两个非常宽松的许可证,意味着你可以随便复制并修改维基百科的内容(图片内容另有规定),商业化也是被允许的,当然包括投放广告。具体的条款,没时间细看了。

flask框架的回复中显示中文utf8字符,而不是unicode-escape字符串

今天在用flask框架写http服务的时候,发现调用flask的jsonify函数得到的http回复包中的字文是用unicode-escape string表示的。如下:

u5b57\u5173\u6ce8\u6211\u4eec\uff01

有些RESTful工具能够把unicode-escape字符串转成utf8,能够正常显示出中文。但很多编辑器和其它工具只能显示原本的unicode转义字符串,大大妨碍调试。解决方案是用flask的另一个函数:make_response解决这个问题。代码如下:

from flask import Flask, jsonify, make_response


def mk_utf8resp(js):
    '''
    传入一个字典,返回一个json格式的http回复。
    '''
    resp = make_response(json.dumps(js, ensure_ascii=False))
    resp.headers['Content-Type'] = 'application/json'
    return resp

把jsonify(js)换成mk_utf8resp(js),问题解决。