mirror of
https://github.com/LCTT/TranslateProject.git
synced 2026-08-23 04:03:29 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
@@ -1,51 +1,49 @@
|
||||
# [使用 Argbash 来改进你的 Bash 脚本][1]
|
||||
使用 Argbash 来改进你的 Bash 脚本
|
||||
======
|
||||
|
||||

|
||||
|
||||
你编写或维护过有意义的 bash 脚本吗?如果回答是,那么你可能希望它们以标准且健壮的方式接收命令行参数。Fedora 最近得到了[一个很好的附加组件][2],它可以帮助你生成更好的脚本。不用担心,它不会花费你很多时间或精力。
|
||||
|
||||
### 为什么是 Argbash?
|
||||
### 为什么需要 Argbash?
|
||||
|
||||
Bash 是一种解释性的命令行语言,没有标准库。因此,如果你编写 bash 脚本并希望命令行界面符合 [POSIX][3] 和 [GNU CLI][4] 标准,那么你只需习惯两个选项:
|
||||
Bash 是一种解释性的命令行语言,没有标准库。因此,如果你编写 bash 脚本并希望命令行界面符合 [POSIX][3] 和 [GNU CLI][4] 标准,那么你一般只有两种选择:
|
||||
|
||||
1. 直接编写为脚本量身定制的参数解析功能(可使用内置的 `getopts`)。
|
||||
|
||||
2. 使用外部 bash 模块。
|
||||
|
||||
第一个选项看起来非常愚蠢,因为正确实现接口并非易事。但是,从 [Stack Overflow][5] 到 [Bash Hackers][6] wiki 的各种站点上,它被认为是最佳选择。
|
||||
第一个选项看起来非常愚蠢,因为正确实现接口并非易事。但是,从 [Stack Overflow][5] 到 [Bash Hackers][6] wiki 的各种站点上,它却被认为是最佳选择。
|
||||
|
||||
第二个选项看起来更聪明,但使用模块有它自己的问题。最大的问题是你必须将其代码与脚本捆绑在一起。这可能意味着:
|
||||
|
||||
* 你将库作为单独的文件分发
|
||||
* 要么,你将库作为单独的文件分发
|
||||
* 或者,在脚本的开头包含库代码
|
||||
|
||||
* 在脚本的开头包含库代码
|
||||
有两个文件而不是一个是愚蠢的;但采用一个文件的话,会让一堆上千行的复杂代码污染了你的脚本。
|
||||
|
||||
有两个文件而不是一个是愚蠢的,但一个文件会使用一串超过千行的复杂代码去污染你的脚本。(to 校正:这句话原文不知该如何理解)
|
||||
|
||||
这是 Argbash [项目诞生][7]的主要原因。Argbash 是一个代码生成器,它为你的脚本生成一个量身定制的解析库。与其他 bash 模块的通用代码不同,它生成脚本所需的最少代码。此外,如果你不需要 100% 符合这些 CLI 标准,你可以生成更简单的代码。
|
||||
这是 Argbash [项目诞生][7]的主要原因。Argbash 是一个代码生成器,它为你的脚本生成一个量身定制的解析库。与其他 bash 模块的通用代码不同,它生成你的脚本所需的最少代码。此外,如果你不需要 100% 符合那些 CLI 标准的话,你可以生成更简单的代码。
|
||||
|
||||
### 示例
|
||||
|
||||
### 分析
|
||||
#### 分析
|
||||
|
||||
假设你要实现一个脚本,它可以在终端窗口中[绘制条形图][8],你可以通过多次重复选择一个字符来做到这一点。这意味着你需要从命令行获取以下信息:
|
||||
假设你要实现一个脚本,它可以在终端窗口中[绘制条形图][8],你可以通过重复一个字符选定的次数来做到这一点。这意味着你需要从命令行获取以下信息:
|
||||
|
||||
* _这个字符是直线的元素。如果未指定,使用破折号。_ 在命令行上,这将是单值位置参数 _character_,其默认值为 -。
|
||||
* _哪个字符是组成该行的元素。如果未指定,使用破折号 `-`。_ 在命令行上,这是个单值定位参数 `character`,其默认值为 `-`。(LCTT 译注:定位参数是指确定位置的参数,此处 `character` 需是命令行的第一个参数)
|
||||
* _直线的长度。如果未指定,会选择 `80`。_ 这是一个单值可选参数 `length`,默认值为 `80`。
|
||||
* _Verbose 模式(用于调试)。_ 这是一个布尔型参数 `verbose`,默认情况下关闭。
|
||||
|
||||
* _直线的长度。如果未指定,会选择 80。_ 这是一个单值可选参数 _-length_,默认值为 80。
|
||||
由于脚本的主体非常简单,因此本文主要关注从命令行获取用户的输入到合适的脚本变量。Argbash 生成的代码会将参数解析结果保存到 shell 变量 `_arg_character`、`_arg_length` 和 `_arg_verbose` 当中。
|
||||
|
||||
* _Verbose 模式(用于调试)。_ 这是一个布尔型参数 _verbose_,默认情况下关闭。
|
||||
#### 执行
|
||||
|
||||
由于脚本的主体非常简单,因此本文主要关注从命令行获取用户的输入到合适的脚本变量。Argbash 生成的代码将解析结果保存到 shell 变量 _arg\_character_, _arg\_length_ 和 _arg\_verbose_。
|
||||
接下来,你还需要 `argbash-init` 和 `argbash` bash 脚本,它们是 argbash 包的一部分。因此,运行以下命令:
|
||||
|
||||
### 执行
|
||||
|
||||
要继续下去,你还需要 _argbash-init_ 和 _argbash_ bash 脚本,它们是 _argbash_ 包的一部分。因此,运行以下命令:
|
||||
```
|
||||
sudo dnf install argbash
|
||||
```
|
||||
|
||||
然后,使用 _argbash-init_ 来为 _argbash_ 生成模板,它会生成可执行脚本。你需要三个参数:一个名为 _character_ 的位置参数,一个可选的 _length_ 参数以及一个可选的布尔 _verbose_。将这些传递给 _argbash-init_,然后将输出传递给 _argbash_ :
|
||||
然后,使用 `argbash-init` 来为 `argbash` 生成模板,它会生成可执行脚本。你需要三个参数:一个名为 `character` 的定位参数,一个可选的 `length` 参数以及一个可选的布尔 `verbose`。将这些传递给 `argbash-init`,然后将输出传递给 `argbash` :
|
||||
```
|
||||
argbash-init --pos character --opt length --opt-bool verbose script-template.sh
|
||||
argbash script-template.sh -o script
|
||||
@@ -53,6 +51,7 @@ argbash script-template.sh -o script
|
||||
```
|
||||
|
||||
看到帮助信息了吗?看起来该脚本不知道字符参数的默认选项。因此,看一下 [Argbash API][9],然后通过编辑脚本的模板部分来解决问题:
|
||||
|
||||
```
|
||||
# ...
|
||||
# ARG_OPTIONAL_SINGLE([length],[l],[Length of the line],[80])
|
||||
@@ -62,7 +61,8 @@ argbash script-template.sh -o script
|
||||
# ...
|
||||
```
|
||||
|
||||
Argbash 非常智能,它试图让每个生成的脚本都成为自己的模板,这意味着你不必担心存储源模版以供进一步使用。你不应该丢失生成的 bash 脚本。现在,尝试重新生成将来的线条绘图以按预期工作:(to 校正:这里不清楚)
|
||||
Argbash 非常智能,它试图让每个生成的脚本都成为自己的模板,这意味着你不需要存储源模版以供进一步使用,你也不要丢掉生成的 bash 脚本。现在,尝试重新生成如你所预期的下一个线条绘图脚本:
|
||||
|
||||
```
|
||||
argbash script -o script
|
||||
./script
|
||||
@@ -72,24 +72,24 @@ argbash script -o script
|
||||
|
||||
### 结论
|
||||
|
||||
你可能会发现包含解析代码的部分很长,但考虑到它允许你调用 _./script.sh x -Vl50_,它将被理解为与 _./script -V -l 50 x_ 相同的方式。确实需要一些代码才能做到这一点。
|
||||
你可能会发现包含解析代码的部分很长,但考虑到它允许你以 `./script.sh x -Vl50` 的方式调用,并且能像 `./script -V -l 50 x` 一样工作。确实需要一些代码才能做到这一点。
|
||||
|
||||
但是,通过调用 _argbash-init_ 并将参数 _-mode_ 设置为 _minimal_,你可以将生成的代码复杂度和解析能力之间的平衡转向更简单的代码。这个选项将脚本的大小减少了大约 20 行,这相当于生成的解析代码大小减少了大约 25%。另一方面,_full_ 选项使脚本更加智能。
|
||||
但是,通过调用 `argbash-init` 并将参数 `-mode` 设置为 `minimal`,你可以平衡生成的代码复杂度和解析能力,而转向更简单的代码。这个选项将脚本的大小减少了大约 20 行,这相当于生成的解析代码大小减少了大约 25%。另一方面,`full` 模式使脚本更加智能。
|
||||
|
||||
如果你想要检查生成的代码,请给 _argbash_ 提供参数 _-commented_,它会将注释放入解析代码中,从而揭示各个部分背后的意图。与其他参数解析库相比较,如 [shflags][10], [argsparse][11] 或 [bash-modules/arguments][12],你将看到 Argbash 强大的简单性。如果出现了严重的错误,你需要快速修复解析功能中的一个故障,Argbash 也允许你这样做。
|
||||
如果你想要检查生成的代码,请给 `argbash` 提供参数 `-commented`,它会将注释放入解析代码中,从而揭示各个部分背后的意图。与其他参数解析库相比较,如 [shflags][10], [argsparse][11] 或 [bash-modules/arguments][12],你将看到 Argbash 强大的简单性。如果出现了严重的错误,你需要快速修复解析功能中的一个故障,Argbash 也允许你这样做。
|
||||
|
||||
由于你很有可能是 Fedora 用户,因此你可以享受从官方仓库安装命令行 Argbash 的便利。然而,在你的服务中还有一个[在线解析代码生成器][13]。此外,如果你在服务器上使用 Docker 工作,你可以试试 [Argbash Docker 镜像][14]。
|
||||
由于你很有可能是 Fedora 用户,因此你可以享受从官方仓库安装命令行 Argbash 的便利。不过,也有一个[在线解析代码生成器][13]服务可以使用。此外,如果你在服务器上使用 Docker 工作,你可以试试 [Argbash Docker 镜像][14]。
|
||||
|
||||
因此,请享受并确保你的脚本具有令用户满意的命令行界面。Argbash 随时为你提供帮助,你只需付出很少的努力。
|
||||
这样你可以让你的脚本具有令用户满意的命令行界面。Argbash 随时为你提供帮助,你只需付出很少的努力。
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/improve-bash-scripts-argbash/
|
||||
|
||||
作者:[Matěj Týč ][a]
|
||||
作者:[Matěj Týč][a]
|
||||
译者:[MjSeven](https://github.com/MjSeven)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
125
published/20171214 Peeking into your Linux packages.md
Normal file
125
published/20171214 Peeking into your Linux packages.md
Normal file
@@ -0,0 +1,125 @@
|
||||
一窥你安装的 Linux 软件包
|
||||
======
|
||||
> 这些最有用的命令可以让你了解安装在你的 Debian 类的 Linux 系统上的包的情况。
|
||||
|
||||

|
||||
|
||||
你有没有想过你的 Linux 系统上安装了几千个软件包? 是的,我说的是“千”。 即使是相当一般的 Linux 系统也可能安装了上千个软件包。 有很多方法可以获得这些包到底是什么包的详细信息。
|
||||
|
||||
首先,要在基于 Debian 的发行版(如 Ubuntu)上快速得到已安装的软件包数量,请使用 `apt list --installed`, 如下:
|
||||
|
||||
```
|
||||
$ apt list --installed | wc -l
|
||||
2067
|
||||
```
|
||||
|
||||
这个数字实际上多了一个,因为输出中包含了 “Listing ...” 作为它的第一行。 这个命令会更准确:
|
||||
|
||||
```
|
||||
$ apt list --installed | grep -v "^Listing" | wc -l
|
||||
2066
|
||||
```
|
||||
|
||||
要获得所有这些包的详细信息,请按以下方式浏览列表:
|
||||
|
||||
```
|
||||
$ apt list --installed | more
|
||||
Listing...
|
||||
a11y-profile-manager-indicator/xenial,now 0.1.10-0ubuntu3 amd64 [installed]
|
||||
account-plugin-aim/xenial,now 3.12.11-0ubuntu3 amd64 [installed]
|
||||
account-plugin-facebook/xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
|
||||
account-plugin-flickr/xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
|
||||
account-plugin-google/xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
|
||||
account-plugin-jabber/xenial,now 3.12.11-0ubuntu3 amd64 [installed]
|
||||
account-plugin-salut/xenial,now 3.12.11-0ubuntu3 amd64 [installed]
|
||||
|
||||
```
|
||||
|
||||
这需要观察很多细节 —— 特别是让你的眼睛在所有 2000 多个文件中徘徊。 它包含包名称、版本等,以及更多但并不是以最易于我们人类解析的显示信息。 `dpkg-query` 使得描述更容易理解,但这些描述会塞满你的命令窗口,除非窗口非常宽。 因此,为了让此篇文章更容易阅读,下面的数据显示已经分成了左右两侧。
|
||||
|
||||
左侧:
|
||||
|
||||
```
|
||||
$ dpkg-query -l | more
|
||||
Desired=Unknown/Install/Remove/Purge/Hold
|
||||
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|
||||
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
|
||||
||/ Name Version
|
||||
+++-==============================================-=================================-
|
||||
ii a11y-profile-manager-indicator 0.1.10-0ubuntu3
|
||||
ii account-plugin-aim 3.12.11-0ubuntu3
|
||||
ii account-plugin-facebook 0.12+16.04.20160126-0ubuntu1
|
||||
ii account-plugin-flickr 0.12+16.04.20160126-0ubuntu1
|
||||
ii account-plugin-google 0.12+16.04.20160126-0ubuntu1
|
||||
ii account-plugin-jabber 3.12.11-0ubuntu3
|
||||
ii account-plugin-salut 3.12.11-0ubuntu3
|
||||
ii account-plugin-twitter 0.12+16.04.20160126-0ubuntu1
|
||||
rc account-plugin-windows-live 0.11+14.04.20140409.1-0ubuntu2
|
||||
```
|
||||
|
||||
右侧:
|
||||
|
||||
```
|
||||
Architecture Description
|
||||
============-=====================================================================
|
||||
amd64 Accessibility Profile Manager - Unity desktop indicator
|
||||
amd64 Messaging account plugin for AIM
|
||||
all GNOME Control Center account plugin for single signon - facebook
|
||||
all GNOME Control Center account plugin for single signon - flickr
|
||||
all GNOME Control Center account plugin for single signon
|
||||
amd64 Messaging account plugin for Jabber/XMPP
|
||||
amd64 Messaging account plugin for Local XMPP (Salut)
|
||||
all GNOME Control Center account plugin for single signon - twitter
|
||||
all GNOME Control Center account plugin for single signon - windows live
|
||||
```
|
||||
|
||||
每行开头的 `ii` 和 `rc` 名称(见上文“左侧”)是包状态指示符。 第一个字母表示包的预期状态:
|
||||
|
||||
- `u` -- 未知
|
||||
- `i` -- 安装
|
||||
- `r` -- 移除/反安装
|
||||
- `p` -- 清除(也包括配置文件)
|
||||
- `h` -- 保留
|
||||
|
||||
第二个代表包的当前状态:
|
||||
|
||||
- `n` -- 未安装
|
||||
- `i` -- 已安装
|
||||
- `c` -- 配置文件(只安装了配置文件)
|
||||
- `U` -- 未打包
|
||||
- `F` -- 半配置(出于某些原因配置失败)
|
||||
- `h` -- 半安装(出于某些原因配置失败)
|
||||
- `W` -- 等待触发(该包等待另外一个包的触发器)
|
||||
- `t` -- 待定触发(该包被触发)
|
||||
|
||||
在通常的双字符字段末尾添加的 `R` 表示需要重新安装。 你可能永远不会碰到这些。
|
||||
|
||||
快速查看整体包状态的一种简单方法是计算在不同状态中包含的包的数量:
|
||||
|
||||
```
|
||||
$ dpkg-query -l | tail -n +6 | awk '{print $1}' | sort | uniq -c
|
||||
2066 ii
|
||||
134 rc
|
||||
```
|
||||
|
||||
我从上面的 `dpkg-query` 输出中排除了前五行,因为这些是标题行,会混淆输出。
|
||||
|
||||
这两行基本上告诉我们,在这个系统上,应该安装了 2066 个软件包,而 134 个其他的软件包已被删除,但留下了配置文件。 你始终可以使用以下命令删除程序包的剩余配置文件:
|
||||
|
||||
```
|
||||
$ sudo dpkg --purge xfont-mathml
|
||||
```
|
||||
|
||||
请注意,如果程序包二进制文件和配置文件都已经安装了,则上面的命令将两者都删除。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3242808/linux/peeking-into-your-linux-packages.html
|
||||
|
||||
作者:[Sandra Henry-Stocker][a]
|
||||
译者:[Flowsnow](https://github.com/Flowsnow)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
|
||||
@@ -1,42 +1,39 @@
|
||||
为什么 Python 这么慢?
|
||||
============================================================
|
||||
==========
|
||||
|
||||
Python 现在越来越火,已经迅速扩张到包括 DevOps、数据科学、web 开发、信息安全等各个领域当中。
|
||||
Python 现在越来越火,已经迅速扩张到包括 DevOps、数据科学、Web 开发、信息安全等各个领域当中。
|
||||
|
||||
然而,相比起 Python 扩张的速度,Python 代码的运行速度就显得有点逊色了。
|
||||
|
||||
|
||||

|
||||
|
||||
> 在代码运行速度方面,Java、C、C++、C#和 Python 要如何进行比较呢?并没有一个放之四海而皆准的标准,因为具体结果很大程度上取决于运行的程序类型,而<ruby>语言基准测试<rt>Computer Language Benchmarks Games</rt></ruby>可以作为[衡量的一个方面][5]。
|
||||
> 在代码运行速度方面,Java、C、C++、C# 和 Python 要如何进行比较呢?并没有一个放之四海而皆准的标准,因为具体结果很大程度上取决于运行的程序类型,而<ruby>语言基准测试<rt>Computer Language Benchmarks Games</rt></ruby>可以作为[衡量的一个方面][5]。
|
||||
|
||||
根据我这些年来进行语言基准测试的经验来看,Python 比很多语言运行起来都要慢。无论是使用 [JIT][7] 编译器的 C#、Java,还是使用 [AOT][8] 编译器的 C、C ++,又或者是 JavaScript 这些解释型语言,Python 都[比它们运行得慢][6]。
|
||||
根据我这些年来进行语言基准测试的经验来看,Python 比很多语言运行起来都要慢。无论是使用 [JIT][7] 编译器的 C#、Java,还是使用 [AOT][8] 编译器的 C、C++,又或者是 JavaScript 这些解释型语言,Python 都[比它们运行得慢][6]。
|
||||
|
||||
注意:对于文中的 Python ,一般指 CPython 这个官方的实现。当然我也会在本文中提到其它语言的 Python 实现。
|
||||
注意:对于文中的 “Python” ,一般指 CPython 这个官方的实现。当然我也会在本文中提到其它语言的 Python 实现。
|
||||
|
||||
> 我要回答的是这个问题:对于一个类似的程序,Python 要比其它语言慢 2 到 10 倍不等,这其中的原因是什么?又有没有改善的方法呢?
|
||||
|
||||
主流的说法有这些:
|
||||
|
||||
* “是<ruby>全局解释器锁<rt>Global Interpreter Lock</rt></ruby>(GIL)的原因”
|
||||
|
||||
* “是因为 Python 是解释型语言而不是编译型语言”
|
||||
|
||||
* “是因为 Python 是一种动态类型的语言”
|
||||
|
||||
哪一个才是是影响 Python 运行效率的主要原因呢?
|
||||
|
||||
### 是全局解释器锁的原因吗?
|
||||
|
||||
现在很多计算机都配备了具有多个核的 CPU ,有时甚至还会有多个处理器。为了更充分利用它们的处理能力,操作系统定义了一个称为线程的低级结构。某一个进程(例如 Chrome 浏览器)可以建立多个线程,在系统内执行不同的操作。在这种情况下,CPU 密集型进程就可以跨核心共享负载了,这样的做法可以大大提高应用程序的运行效率。
|
||||
现在很多计算机都配备了具有多个核的 CPU ,有时甚至还会有多个处理器。为了更充分利用它们的处理能力,操作系统定义了一个称为线程的低级结构。某一个进程(例如 Chrome 浏览器)可以建立多个线程,在系统内执行不同的操作。在这种情况下,CPU 密集型进程就可以跨核心分担负载了,这样的做法可以大大提高应用程序的运行效率。
|
||||
|
||||
例如在我写这篇文章时,我的 Chrome 浏览器打开了 44 个线程。要知道的是,基于 POSIX 的操作系统(例如 Mac OS、Linux)和 Windows 操作系统的线程结构、API 都是不同的,因此操作系统还负责对各个线程的调度。
|
||||
例如在我写这篇文章时,我的 Chrome 浏览器打开了 44 个线程。需要提及的是,基于 POSIX 的操作系统(例如 Mac OS、Linux)和 Windows 操作系统的线程结构、API 都是不同的,因此操作系统还负责对各个线程的调度。
|
||||
|
||||
如果你还没有写过多线程执行的代码,你就需要了解一下线程锁的概念了。多线程进程比单线程进程更为复杂,是因为需要使用线程锁来确保同一个内存地址中的数据不会被多个线程同时访问或更改。
|
||||
|
||||
CPython 解释器在创建变量时,首先会分配内存,然后对该变量的引用进行计数,这称为<ruby>引用计数<rt>reference counting</rt></ruby>。如果变量的引用数变为 0,这个变量就会从内存中释放掉。这就是在 for 循环代码块内创建临时变量不会增加内存消耗的原因。
|
||||
|
||||
而当多个线程内共享一个变量时,CPython 锁定引用计数的关键就在于使用了 GIL,它会谨慎地控制线程的执行情况,无论同时存在多少个线程,每次只允许一个线程进行操作。
|
||||
而当多个线程内共享一个变量时,CPython 锁定引用计数的关键就在于使用了 GIL,它会谨慎地控制线程的执行情况,无论同时存在多少个线程,解释器每次只允许一个线程进行操作。
|
||||
|
||||
#### 这会对 Python 程序的性能有什么影响?
|
||||
|
||||
@@ -45,9 +42,10 @@ CPython 解释器在创建变量时,首先会分配内存,然后对该变量
|
||||
但如果你通过在单进程中使用多线程实现并发,并且是 IO 密集型(例如网络 IO 或磁盘 IO)的线程,GIL 竞争的效果就很明显了。
|
||||
|
||||

|
||||
由 David Beazley 提供的 GIL 竞争情况图[http://dabeaz.blogspot.com/2010/01/python-gil-visualized.html][1]
|
||||
|
||||
对于一个 web 应用(例如 Django),同时还使用了 WSGI,那么对这个 web 应用的每一个请求都是一个单独的 Python 进程,而且每个请求只有一个锁。同时 Python 解释器的启动也比较慢,某些 WSGI 实现还具有“守护进程模式”,[就会导致 Python 进程非常繁忙][9]。
|
||||
*由 David Beazley 提供的 GIL 竞争情况图[http://dabeaz.blogspot.com/2010/01/python-gil-visualized.html][1]*
|
||||
|
||||
对于一个 web 应用(例如 Django),同时还使用了 WSGI,那么对这个 web 应用的每一个请求都运行一个**单独**的 Python 解释器,而且每个请求只有一个锁。同时因为 Python 解释器的启动比较慢,某些 WSGI 实现还具有“守护进程模式”,[可以使 Python 进程一直就绪][9]。
|
||||
|
||||
#### 其它的 Python 解释器表现如何?
|
||||
|
||||
@@ -57,46 +55,43 @@ CPython 解释器在创建变量时,首先会分配内存,然后对该变量
|
||||
|
||||
#### JavaScript 在这方面又是怎样做的呢?
|
||||
|
||||
所有的 Javascript 引擎使用的都是 [mark-and-sweep 垃圾收集算法][12],而 GIL 使用的则是 CPython 的内存管理算法。因此 JavaScript 没有 GIL,而且它是单线程的,也不需要用到 GIL, JavaScript 的事件循环和 Promise/Callback 模式实现了以异步编程的方式代替并发。在 Python 当中也有一个类似的 asyncio 事件循环。
|
||||
所有的 Javascript 引擎使用的都是 [mark-and-sweep 垃圾收集算法][12],而 GIL 使用的则是 CPython 的内存管理算法。
|
||||
|
||||
JavaScript 没有 GIL,而且它是单线程的,也不需要用到 GIL, JavaScript 的事件循环和 Promise/Callback 模式实现了以异步编程的方式代替并发。在 Python 当中也有一个类似的 asyncio 事件循环。
|
||||
|
||||
### 是因为 Python 是解释型语言吗?
|
||||
|
||||
我经常会听到这个说法,但其实当终端上执行 `python myscript.py` 之后,CPython 会对代码进行一系列的读取、语法分析、解析、编译、解释和执行的操作。
|
||||
我经常会听到这个说法,但是这过于粗陋地简化了 Python 所实际做的工作了。其实当终端上执行 `python myscript.py` 之后,CPython 会对代码进行一系列的读取、语法分析、解析、编译、解释和执行的操作。
|
||||
|
||||
如果你对这一系列过程感兴趣,也可以阅读一下我之前的文章:
|
||||
如果你对这一系列过程感兴趣,也可以阅读一下我之前的文章:[在 6 分钟内修改 Python 语言][13] 。
|
||||
|
||||
[在 6 分钟内修改 Python 语言][13]
|
||||
`.pyc` 文件的创建是这个过程的重点。在代码编译阶段,Python 3 会将字节码序列写入 `__pycache__/` 下的文件中,而 Python 2 则会将字节码序列写入当前目录的 `.pyc` 文件中。对于你编写的脚本、导入的所有代码以及第三方模块都是如此。
|
||||
|
||||
创建 `.pyc` 文件是这个过程的重点。在代码编译阶段,Python 3 会将字节码序列写入 `__pycache__/` 下的文件中,而 Python 2 则会将字节码序列写入当前目录的 `.pyc` 文件中。对于你编写的脚本、导入的所有代码以及第三方模块都是如此。
|
||||
|
||||
因此,绝大多数情况下(除非你的代码是一次性的……),Python 都会解释字节码并执行。与 Java、C#.NET 相比:
|
||||
因此,绝大多数情况下(除非你的代码是一次性的……),Python 都会解释字节码并本地执行。与 Java、C#.NET 相比:
|
||||
|
||||
> Java 代码会被编译为“中间语言”,由 Java 虚拟机读取字节码,并将其即时编译为机器码。.NET CIL 也是如此,.NET CLR(Common-Language-Runtime)将字节码即时编译为机器码。
|
||||
|
||||
既然 Python 不像 Java 和 C# 那样使用虚拟机或某种字节码,为什么 Python 在基准测试中仍然比 Java 和 C# 慢得多呢?首要原因是,.NET 和 Java 都是 JIT 编译的。
|
||||
既然 Python 像 Java 和 C# 那样都使用虚拟机或某种字节码,为什么 Python 在基准测试中仍然比 Java 和 C# 慢得多呢?首要原因是,.NET 和 Java 都是 JIT 编译的。
|
||||
|
||||
<ruby>即时编译<rt>Just-in-time compilation</rt></ruby>(JIT)需要一种中间语言,以便将代码拆分为多个块(或多个帧)。而<ruby>提前编译器<rt>ahead of time compiler</rt></ruby>(AOT)则需要确保 CPU 在任何交互发生之前理解每一行代码。
|
||||
<ruby>即时<rt>Just-in-time</rt></ruby>(JIT)编译需要一种中间语言,以便将代码拆分为多个块(或多个帧)。而<ruby>提前<rt>ahead of time</rt></ruby>(AOT)编译器则需要确保 CPU 在任何交互发生之前理解每一行代码。
|
||||
|
||||
JIT 本身是不会让执行速度加快的,因为它执行的仍然是同样的字节码序列。但是 JIT 会允许运行时的优化。一个优秀的 JIT 优化器会分析出程序的哪些部分会被多次执行,这就是程序中的“热点”,然后,优化器会将这些热点编译得更为高效以实现优化。
|
||||
JIT 本身不会使执行速度加快,因为它执行的仍然是同样的字节码序列。但是 JIT 会允许在运行时进行优化。一个优秀的 JIT 优化器会分析出程序的哪些部分会被多次执行,这就是程序中的“热点”,然后优化器会将这些代码替换为更有效率的版本以实现优化。
|
||||
|
||||
这就意味着如果你的程序是多次地重复相同的操作时,有可能会被优化器优化得更快。而且,Java 和 C# 是强类型语言,因此优化器对代码的判断可以更为准确。
|
||||
这就意味着如果你的程序是多次重复相同的操作时,有可能会被优化器优化得更快。而且,Java 和 C# 是强类型语言,因此优化器对代码的判断可以更为准确。
|
||||
|
||||
PyPy 使用了明显快于 CPython 的 JIT。更详细的结果可以在这篇性能基准测试文章中看到:
|
||||
|
||||
[哪一个 Python 版本最快?][15]
|
||||
PyPy 使用了明显快于 CPython 的 JIT。更详细的结果可以在这篇性能基准测试文章中看到:[哪一个 Python 版本最快?][15]。
|
||||
|
||||
#### 那为什么 CPython 不使用 JIT 呢?
|
||||
|
||||
JIT 也不是完美的,它的一个显著缺点就在于启动时间。 CPython 的启动时间已经相对比较慢,而 PyPy 比 CPython 启动还要慢 2 到 3 倍,所以 Java 虚拟机启动速度已经是出了名的慢了。.NET CLR则通过在系统启动时自启动来优化体验, 甚至还有专门运行 CLR 的操作系统。
|
||||
JIT 也不是完美的,它的一个显著缺点就在于启动时间。 CPython 的启动时间已经相对比较慢,而 PyPy 比 CPython 启动还要慢 2 到 3 倍。Java 虚拟机启动速度也是出了名的慢。.NET CLR 则通过在系统启动时启动来优化体验,而 CLR 的开发者也是在 CLR 上开发该操作系统。
|
||||
|
||||
因此如果你的 Python 进程在一次启动后就长时间运行,JIT 就比较有意义了,因为代码里有“热点”可以优化。
|
||||
因此如果你有个长时间运行的单一 Python 进程,JIT 就比较有意义了,因为代码里有“热点”可以优化。
|
||||
|
||||
尽管如此,CPython 仍然是通用的代码实现。设想如果使用 Python 开发命令行程序,但每次调用 CLI 时都必须等待 JIT 缓慢启动,这种体验就相当不好了。
|
||||
不过,CPython 是个通用的实现。设想如果使用 Python 开发命令行程序,但每次调用 CLI 时都必须等待 JIT 缓慢启动,这种体验就相当不好了。
|
||||
|
||||
CPython 必须通过大量用例的测试,才有可能实现[将 JIT 插入到 CPython 中][17],但这个改进工作的进度基本处于停滞不前的状态。
|
||||
CPython 试图用于各种使用情况。有可能实现[将 JIT 插入到 CPython 中][17],但这个改进工作的进度基本处于停滞不前的状态。
|
||||
|
||||
> 如果你想充分发挥 JIT 的优势,请使用PyPy。
|
||||
> 如果你想充分发挥 JIT 的优势,请使用 PyPy。
|
||||
|
||||
### 是因为 Python 是一种动态类型的语言吗?
|
||||
|
||||
@@ -113,11 +108,11 @@ a = "foo"
|
||||
|
||||
Python 也实现了这样的转换,但用户看不到这些转换,也不需要关心这些转换。
|
||||
|
||||
变量类型不固定并不是 Python 运行慢的原因,Python 通过巧妙的设计让用户可以让各种结构变得动态:可以在运行时更改对象上的方法,也可以在运行时让模块调用新声明的值,几乎可以做到任何事。
|
||||
不用必须声明类型并不是为了使 Python 运行慢,Python 的设计是让用户可以让各种东西变得动态:可以在运行时更改对象上的方法,也可以在运行时动态添加底层系统调用到值的声明上,几乎可以做到任何事。
|
||||
|
||||
但也正是这种设计使得 Python 的优化难度变得很大。
|
||||
但也正是这种设计使得 Python 的优化异常的难。
|
||||
|
||||
为了证明我的观点,我使用了一个 `dtrace` 这个 Mac OS 上的系统调用跟踪工具。CPython 中没有内置 dTrace,因此必须重新对 CPython 进行编译。以下使用 Python 3.6.6 进行为例:
|
||||
为了证明我的观点,我使用了一个 Mac OS 上的系统调用跟踪工具 DTrace。CPython 发布版本中没有内置 DTrace,因此必须重新对 CPython 进行编译。以下以 Python 3.6.6 为例:
|
||||
|
||||
```
|
||||
wget https://github.com/python/cpython/archive/v3.6.6.zip
|
||||
@@ -127,22 +122,19 @@ cd v3.6.6
|
||||
make
|
||||
```
|
||||
|
||||
这样 `python.exe` 将使用 dtrace 追踪所有代码。[Paul Ross 也作过关于 dtrace 的闪电演讲][19]。你可以下载 Python 的 dtrace 启动文件来查看函数调用、系统调用、CPU 时间、执行时间,以及各种其它的内容。
|
||||
这样 `python.exe` 将使用 DTrace 追踪所有代码。[Paul Ross 也作过关于 DTrace 的闪电演讲][19]。你可以下载 Python 的 DTrace 启动文件来查看函数调用、执行时间、CPU 时间、系统调用,以及各种其它的内容。
|
||||
|
||||
`sudo dtrace -s toolkit/<tracer>.d -c ‘../cpython/python.exe script.py’`
|
||||
```
|
||||
sudo dtrace -s toolkit/<tracer>.d -c ‘../cpython/python.exe script.py’
|
||||
```
|
||||
|
||||
`py_callflow` 追踪器显示了程序里调用的所有函数。
|
||||
|
||||
|
||||

|
||||
`py_callflow` 追踪器[显示](https://cdn-images-1.medium.com/max/1600/1*Lz4UdUi4EwknJ0IcpSJ52g.gif)了程序里调用的所有函数。
|
||||
|
||||
那么,Python 的动态类型会让它变慢吗?
|
||||
|
||||
* 类型比较和类型转换消耗的资源是比较多的,每次读取、写入或引用变量时都会检查变量的类型
|
||||
|
||||
* Python 的动态程度让它难以被优化,因此很多 Python 的替代品都为了提升速度而在灵活性方面作出了妥协
|
||||
|
||||
* 而 [Cython][2] 结合了 C 的静态类型和 Python 来优化已知类型的代码,它可以将[性能提升][3] 84 倍。
|
||||
* 类型比较和类型转换消耗的资源是比较多的,每次读取、写入或引用变量时都会检查变量的类型
|
||||
* Python 的动态程度让它难以被优化,因此很多 Python 的替代品能够如此快都是为了提升速度而在灵活性方面作出了妥协
|
||||
* 而 [Cython][2] 结合了 C 的静态类型和 Python 来优化已知类型的代码,它[可以将][3]性能提升 **84 倍**。
|
||||
|
||||
### 总结
|
||||
|
||||
@@ -158,7 +150,7 @@ make
|
||||
|
||||
Jake VDP 的优秀文章(略微过时) [https://jakevdp.github.io/blog/2014/05/09/why-python-is-slow/][21]
|
||||
|
||||
Dave Beazley’s 关于 GIL 的演讲 [http://www.dabeaz.com/python/GIL.pdf][22]
|
||||
Dave Beazley 关于 GIL 的演讲 [http://www.dabeaz.com/python/GIL.pdf][22]
|
||||
|
||||
JIT 编译器的那些事 [https://hacks.mozilla.org/2017/02/a-crash-course-in-just-in-time-jit-compilers/][23]
|
||||
|
||||
@@ -169,7 +161,7 @@ via: https://hackernoon.com/why-is-python-so-slow-e5074b6fe55b
|
||||
作者:[Anthony Shaw][a]
|
||||
选题:[oska874][b]
|
||||
译者:[HankChow](https://github.com/HankChow)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
22
sign.md
22
sign.md
@@ -1,22 +0,0 @@
|
||||
|
||||
---
|
||||
|
||||
via:来源链接
|
||||
|
||||
作者:[作者名][a]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,
|
||||
[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:作者链接
|
||||
[1]:文内链接
|
||||
[2]:
|
||||
[3]:
|
||||
[4]:
|
||||
[5]:
|
||||
[6]:
|
||||
[7]:
|
||||
[8]:
|
||||
[9]:
|
||||
@@ -1,3 +1,5 @@
|
||||
thecyanbird translating
|
||||
|
||||
Where Vim Came From
|
||||
======
|
||||
I recently stumbled across a file format known as Intel HEX. As far as I can gather, Intel HEX files (which use the `.hex` extension) are meant to make binary images less opaque by encoding them as lines of hexadecimal digits. Apparently they are used by people who program microcontrollers or need to burn data into ROM. In any case, when I opened up a HEX file in Vim for the first time, I discovered something shocking. Here was this file format that, at least to me, was deeply esoteric, but Vim already knew all about it. Each line of a HEX file is a record divided into different fields—Vim had gone ahead and colored each of the fields a different color. `set ft?` I asked, in awe. `filetype=hex`, Vim answered, triumphant.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
FSSlc translating
|
||||
|
||||
How To Find The Mounted Filesystem Type In Linux
|
||||
======
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
Translating by jlztan
|
||||
|
||||
Top 10 Raspberry Pi blogs to follow
|
||||
======
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
HackChow translating
|
||||
|
||||
5 alerting and visualization tools for sysadmins
|
||||
======
|
||||
These open source tools help users understand system behavior and output, and provide alerts for potential problems.
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
Translating by MjSeven
|
||||
|
||||
|
||||
Kali Linux: What You Must Know Before Using it – FOSS Post
|
||||
======
|
||||

|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
探秘你的Linux软件包
|
||||
======
|
||||
你有没有想过你的 Linux 系统上安装了多少千个软件包? 是的,我说的是“千”。 即使是相当一般的 Linux 系统也可能安装了超过一千个软件包。 有很多方法可以获得这些包到底是什么包的详细信息。
|
||||
|
||||
首先,要在基于 Debian 的发行版(如 Ubuntu)上快速得到已安装的软件包数量,请使用 **apt list --installed**, 如下:
|
||||
|
||||
```
|
||||
$ apt list --installed | wc -l
|
||||
2067
|
||||
|
||||
```
|
||||
|
||||
这个数字实际上多了一个,因为输出中包含了 “Listing ...” 作为它的第一行。 这个命令会更准确:
|
||||
|
||||
```
|
||||
$ apt list --installed | grep -v "^Listing" | wc -l
|
||||
2066
|
||||
|
||||
```
|
||||
|
||||
要获得所有这些包的详细信息,请按以下方式浏览列表:
|
||||
|
||||
```
|
||||
$ apt list --installed | more
|
||||
Listing...
|
||||
a11y-profile-manager-indicator/xenial,now 0.1.10-0ubuntu3 amd64 [installed]
|
||||
account-plugin-aim/xenial,now 3.12.11-0ubuntu3 amd64 [installed]
|
||||
account-plugin-facebook/xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
|
||||
account-plugin-flickr/xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
|
||||
account-plugin-google/xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
|
||||
account-plugin-jabber/xenial,now 3.12.11-0ubuntu3 amd64 [installed]
|
||||
account-plugin-salut/xenial,now 3.12.11-0ubuntu3 amd64 [installed]
|
||||
|
||||
```
|
||||
|
||||
这需要观察很多细节--特别是让你的眼睛在所有 2000 多个文件中徘徊。 它包含包名称,版本等,但不是我们人类解析的最简单的信息显示。 dpkg-query 使得描述更容易理解,但这些描述塞满你的命令窗口,除非窗口非常宽。 因此,为了让此篇文章更容易阅读,下面的数据显示已经分成了左右两侧。
|
||||
|
||||
左侧:
|
||||
```
|
||||
$ dpkg-query -l | more
|
||||
Desired=Unknown/Install/Remove/Purge/Hold
|
||||
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|
||||
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
|
||||
||/ Name Version
|
||||
+++-==============================================-=================================-
|
||||
ii a11y-profile-manager-indicator 0.1.10-0ubuntu3
|
||||
ii account-plugin-aim 3.12.11-0ubuntu3
|
||||
ii account-plugin-facebook 0.12+16.04.20160126-0ubuntu1
|
||||
ii account-plugin-flickr 0.12+16.04.20160126-0ubuntu1
|
||||
ii account-plugin-google 0.12+16.04.20160126-0ubuntu1
|
||||
ii account-plugin-jabber 3.12.11-0ubuntu3
|
||||
ii account-plugin-salut 3.12.11-0ubuntu3
|
||||
ii account-plugin-twitter 0.12+16.04.20160126-0ubuntu1
|
||||
rc account-plugin-windows-live 0.11+14.04.20140409.1-0ubuntu2
|
||||
|
||||
```
|
||||
|
||||
右侧:
|
||||
```
|
||||
Architecture Description
|
||||
============-=====================================================================
|
||||
amd64 Accessibility Profile Manager - Unity desktop indicator
|
||||
amd64 Messaging account plugin for AIM
|
||||
all GNOME Control Center account plugin for single signon - facebook
|
||||
all GNOME Control Center account plugin for single signon - flickr
|
||||
all GNOME Control Center account plugin for single signon
|
||||
amd64 Messaging account plugin for Jabber/XMPP
|
||||
amd64 Messaging account plugin for Local XMPP (Salut)
|
||||
all GNOME Control Center account plugin for single signon - twitter
|
||||
all GNOME Control Center account plugin for single signon - windows live
|
||||
|
||||
```
|
||||
|
||||
每行开头的 “ii” 和 “rc” 名称(见上文“左侧”)是包状态指示符。 第一个字母表示包的理想状态:
|
||||
|
||||
```
|
||||
u -- unknown
|
||||
i -- install
|
||||
r -- remove/deinstall
|
||||
p -- purge (remove including config files)
|
||||
h -- hold
|
||||
|
||||
```
|
||||
|
||||
第二个代表包的当前状态:
|
||||
|
||||
```
|
||||
n -- not-installed
|
||||
i -- installed
|
||||
c -- config-files (only the config files are installed)
|
||||
U -- unpacked
|
||||
F -- half-configured (the configuration failed for some reason)
|
||||
h -- half-installed (installation failed for some reason)
|
||||
W -- triggers-awaited (the package is waiting for a trigger from another package)
|
||||
t -- triggers-pending (the package has been triggered)
|
||||
|
||||
```
|
||||
|
||||
在通常的双字符字段末尾添加的 “R” 表示需要重新安装。 你可能永远不会碰到这些。
|
||||
|
||||
快速查看整体包状态的一种简单方法是计算在不同状态中包含的包的数量:
|
||||
|
||||
```
|
||||
$ dpkg-query -l | tail -n +6 | awk '{print $1}' | sort | uniq -c
|
||||
2066 ii
|
||||
134 rc
|
||||
|
||||
```
|
||||
|
||||
我从上面的 dpkg-query 输出中排除了前五行,因为这些是标题行,会混淆输出。
|
||||
|
||||
这两行基本上告诉我们,在这个系统上,应该安装了 2066 个软件包,而 134 个其他的软件包已被删除,但已经留下了配置文件。 你始终可以使用以下命令删除程序包的剩余配置文件:
|
||||
|
||||
```
|
||||
$ sudo dpkg --purge xfont-mathml
|
||||
```
|
||||
|
||||
请注意,如果程序包二进制文件和配置文件都已经安装了,则上面的命令将两者都删除。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.networkworld.com/article/3242808/linux/peeking-into-your-linux-packages.html
|
||||
|
||||
作者:[Sandra Henry-Stocker][a]
|
||||
译者:[Flowsnow](https://github.com/Flowsnow)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
|
||||
Reference in New Issue
Block a user