为啥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
:
pdb
(import pdb; pdb.set_trace()
, > pp variable
),
print(help(variable))
,
dir(variable)
,
和pprint.pprint( variable.__dict__ )
【讨论】:
以上是关于为啥python不会在启动时自动导入每个模块?的主要内容,如果未能解决你的问题,请参考以下文章