为啥python不会在启动时自动导入每个模块?

Posted

技术标签:

【中文标题】为啥python不会在启动时自动导入每个模块?【英文标题】:Why does python not import every module at startup automatically?为什么python不会在启动时自动导入每个模块? 【发布时间】:2014-01-27 05:43:28 【问题描述】:

我在玩 Python 2.7,每个人都知道,在每个程序开始时,您总是必须导入模块。例如:

import random
import time

for x in range(1, 300):
     print random.randint(1,100)
     time.sleep(1)
print "Done!"

无论如何,我在想,为什么我必须手动导入所有模块?为什么 Python 不就这样全部导入。

当然,我可以理解为什么它不会像这样导入:

from random import randint
from time import *

for x in range(1, 300):
     print randint(1,100)
     sleep(1)
print "Done!"

由于某些函数名称可能会发生冲突。但是,如果您必须定义函数的开始位置,例如 random. in random.randint(1,100)

现在现代计算机如此强大,自动导入每个模块而不是浪费代码行和时间似乎是合乎逻辑的,因为必须找到您需要的模块,然后在可以轻松实现自动化时手动导入它。 那么,为什么 python 在启动时不自动导入每个模块呢?

编辑: 我制作了一个新版本的小程序,它导入了我可以通过运行找到的每个模块:

 import sys
 sys.builtin_module_names

结果如下:

 x = int(1000000)
def test():
    global x
    x -= 1
    print "Iterations Left: ", x
    import __builtin__
    import __main__
    import _ast
    import _bisect
    import _codecs
    import _codecs_cn
    import _codecs_hk
    import _codecs_iso2022
    import _codecs_jp
    import _codecs_kr
    import _codecs_tw
    import _collections
    import _csv
    import _functools
    import _heapq
    import _hotshot
    import _io
    import _json
    import _locale
    import _lsprof
    import _md5
    import _multibytecodec
    import _random
    import _sha
    import _sha256
    import _sha512
    import _sre
    import _struct
    import _subprocess
    import _symtable
    import _warnings
    import _weakref
    import _winreg
    import array
    import audioop
    import binascii
    import cPickle
    import cStringIO
    import cmath
    import datetime
    import errno
    import exceptions
    import future_builtins
    import gc
    import imageop
    import imp
    import itertools
    import marshal
    import math
    import mmap
    import msvcrt
    import nt
    import operator
    import parser
    import signal
    import strop
    import sys
    import thread
    import time
    import xxsubtype
    import zipimport
    import zlib

def start():
    from timeit import Timer
    t = Timer("test()", "from __main__ import test")
    print t.timeit()

start()

【问题讨论】:

如果你想要 php,你知道在哪里可以找到它。享受吧! 您宁愿通过放弃大量内存和执行时间来节省一两行代码? 趋势是删除内置,而不是添加更多。为什么要用大量垃圾污染全局命名空间? 做一个小实验:编写一个导入标准库中所有内容的程序应该相当简单。构建一个并计时,看看它有多重要 sys.builtin_module_names 是内置于解释器中的模块的名称,而不是单独的 Python 或 C 模块。这意味着导入它们几乎是免费的。所以你还没有真正测试过任何东西。 (此外,您会注意到 Python 3.x 中的列表比 2.x 中的短得多,在 3.3+ 中甚至比 3.0-3.2 中的更短。) 【参考方案1】:

因为您不需要所有这些。如果您不需要它们,则加载每个库是没有意义的。

编辑: 我将我的 libs 文件夹复制到一个测试目录,并通过向其中添加一个 __init__.py 文件将其制成一个包。在这个文件中我添加了:

import os
import glob
__all__ = [ os.path.basename(f)[:-3] for f in glob.glob(os.path.dirname(__file__)+"/*.py")]

我创建了一个测试脚本,其中包含:

from Lib import *
print('Hello')

当我尝试在 shell 中运行它时,它所做的只是打印 Tim Peters 的“The Zen of Python”,在我的浏览器中打开 this webcomic(我绝对没有看到的两件事)并引发以下错误:

Traceback (most recent call last):
  File "C:\Users\Hannah\Documents\dropBox\Python\test\test.py", line 1, in <module>
    from Lib import *
AttributeError: 'module' object has no attribute 'crypt'

这需要很长一段时间,大约 10-15 秒

【讨论】:

你不是唯一使用 Python 的人。我一直在使用bif。设计者想出了最常用或最重要的语言功能,并将这些作为核心库的一部分。我不是语言设计师,但我确信这样做时有多种理由可以将您的所有顾虑分开。 从 CPython 3.4 开始,只有 68 个内置函数。有 283 个***模块和包(26 个内置,88 个用 C 实现,169 个用 Python 实现)。大多数人使用这 68 个函数中的相当一部分。很少有人使用这 283 个模块中的很大一部分。【参考方案2】:

也许您想要的功能是自动导入脚本中使用的库,而无需在开始时指定它们。我在网上找到了这个http://www.connellybarnes.com/code/autoimp/

您只需要在脚本开头进行一次导入

from autoimp import *

所有其他模块都是“延迟”加载的,即在它们第一次使用时。

交互式 shell 中的示例:

>>> random.random()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'random' is not defined
>>> from autoimp import *
>>> random.random()
0.0679000238267422

来自文档:

为了最大的懒惰,将命令 "from autoimp import *" 放在你的 PYTHONSTARTUP 文件中。现在,您的交互式会话默认所有模块都可用。

【讨论】:

显式优于隐式。 @user2314737,当您使用 IDE 时,显式导入将为您提供自动完成功能。隐式...? @user2314737 :当你开始有随机的奇怪行为时,想知道哪个符号应该来自哪里以及它实际上来自哪里,并最终花费数周时间将你的代码库重写为一个理智的状态使用显式导入,您会明白您在“懒惰”的错误方面。注意:我在这里说的是代码,而不是 python shell。【参考方案3】:

您导入的每个模块都需要时间来导入。每次启动 Python 时都导入每个内置模块,这会在许多频繁启动新 Python 解释器的重要场景中降低性能。

【讨论】:

【参考方案4】:

Python 确实有一组总是被加载的模块,它的调用 __builtins__ :)。

Python 的内置函数为您提供了import 语句,以使用更多模块扩展您的范围!但正如其他帖子所说,决定你的脚本是否需要这些模块取决于你。 -- 我已经研究过改变__builtins__ 并且我向你保证,明确地导入你需要的东西更好的选择。


((关于不使用from name import *的大吐槽从这里切入))


由于大多数编写 python 最终都变成了在某处打包和安装编写的 python,这是我的 goto 资源集,用于处理 python 的 in著名import:

从坚持使用标准工具和库开始 (https://packaging.python.org/current/) 阅读并理解 Google Python 标准指南 (https://google.github.io/styleguide/pyguide.html), 阅读 Python 之禅 (https://www.python.org/dev/peps/pep-0020/) Pythonic(基本坚持“Python之禅”),https://www.youtube.com/watch?v=wf-BqAjZb8M 用从 The Hitchhikers Guid 到 Python (http://docs.python-guide.org/en/latest/) 的技巧补充您的问题空间 准备好打包您的代码(https://packaging.python.org/distributing/(文档),https://github.com/pypa/sampleproject/(示例)) 通过熟悉以下工具,准备调试他人的和您自己的代码: pdb (import pdb; pdb.set_trace(), &gt; pp variable), print(help(variable)), dir(variable), 和pprint.pprint( variable.__dict__ )

【讨论】:

以上是关于为啥python不会在启动时自动导入每个模块?的主要内容,如果未能解决你的问题,请参考以下文章

TMUX会话不会导入Python模块

ipython启动 自动导入模块 自动%logstart

为啥谷歌地图在首次启动时不会自动缩放到用户位置?

简单的 Python 脚本 - 一旦 python 启动,导入命令就不会执行

在命令行中启动脚本时导入模块

为啥在调试模式下启动 GWT 时,我的断点不会中断