这东西的上下文是什么?是因为什么东西翻到这个上面的。
我粗看感觉是:2.3 以前的 python import 机制太挫了,就实现了一个新的 import 机制。
#8 楼 @hooopo 这个问题比较乱,我思路也没理清楚。我就尽量讲一下我现在对这个问题的认识好了。
这个问题和操作系统有关系,和语言也有关系。或者你可以把一个语言的运行期看成一个操作系统。
首先来看 UNIX: Everything is a file
。假如Everything is a file
只是字面意思,那等于啥都没说。其实这里有两个问题,到哪里去找文件,怎么操作文件。
对于第一个问题,UNIX 的答案是一个树形的File System
/Namespace
。在这里不对这两个概念进行区分。
对于第二个问题,UNIX 的答案是统一的API
/Interface
/Protocol
/Message
。在这里不对这三个概念进行区分。
接着来看 Smalltalk: Everything is an object
。类似的。同样有这两个问题。而对于第一个问题的答案,经典的 Smalltalk 80 并不比 UNIX 更好,Smalltalk 80 就直接让你在名字前面加前缀来区分,就相当于你需要把它脑补成树形的。
对于第一个问题同时也隐含着,一切都可以以文件的形式暴露在文件系统上。这也就是你可以看见/proc
,/sys
这类的目录的原因。
这就是为什么 Plan 9 有file server
,Hurd 有Translator
。Linux 后来也引入了Fuse
。也就是说,有了这个机制和对应的file server
,你可以把一个 zip 文件,mount
成一个目录,可以直接把可以通过 HTTP/FTP 访问到的远端文件mount
成一个本地文件。
假如所有操作系统都原生有这样的机制的话,Python 就没有必要引入 PEP 302 的概念。PEP 302 就是定义了一组 API,让你可以把任何东西,无论它以什么形式存在或者不存在,以 Python object 的形式 import 到 Python 命名空间里,只要你实现了这组 API。
前几天在 Hacker News 上提到的Bitey ,无非就是为 LLVM bitcode 实现了这组 API 罢了。
但是,PEP-302 只是一个 work-around,只能为 Python 解决一小部分的问题。Python 进程运行的时候,事实上有两个独立的 namespace,一个是操作系统的,一个是 Python 的。这也导致了很多麻烦。按照 Python 惯例,并不会把操作系统的 namespace 映射到 Python 的 namespace 里,也不会把 Python 的 namespace 映射到操作系统的 namespace。很多程序,同时会需要一些静态文件,比如图片啥的。而 PEP-302 只定义了get_data
,这其实是远远不够的。而且,即便所有 API 都定义好了,这仍然不够好,尽管这对目前的 Python 来说很可能是唯一的办法。这将导致你为同一件事写了两份代码。
我觉得要真正解决这个问题,得使用 Plan 9 那样的操作系统,把 Python 的 namespace 暴露成/python
,能用 Python 实现file server
,另外,Python 得实现像 Erlang 那样的抢占式调度,那还是 Python 么?我觉得可能还是直接在 Erlang 的基础上改比较靠谱,至少,Erlang 是抢占式调度的,并且也有真正的 namespace 实现 (尽管几乎所有人都用前缀)。
#12 楼 @hooopo 这个还真和 Python 的 import 有点不一样啊。
__import__(xxx)
相当于
content = read("xxx.py")
module = new_module()
eval content at module
sys.modules['xxx'] = module
import xxx
的时候,就是引用 sys.modules['xxx'] 没有就__import__
而在 Ruby 里,require
两次,代码也是只执行一次的吧。所以,你上面那个是load
的语义。require
是没被require
过会去load
一下。而load
必须得eval
,因为直接访问的 namespace 对于所有文件来说是一样的。
#14 楼 @hooopo 我的意思就是说 Python 的 importer 可以跳过 eval,直接返回结果。module 可以随便建的。
比如像下面这样的伪码。
module = new_module()
module['a'] = 1
module['b'] = 2
sys.modules['xxx'] = module
Python 的 importer 机制对 Ruby 实现类似机制的参考意义并不大。
Perl 那个才和 Ruby 比较接近。
http://perldoc.perl.org/functions/require.html
但 Ruby 又不一样,Ruby 还可以reopen class
啊。所以问题就来了,无论如何都要eval
一次,importer 应该返回,源代码,还是 ast,还是 bytecode?但是无论返回哪一种,像bitey
那样的功能该怎么实现?