在借用的代码中删除未使用的导入是否一定安全?

时间:2013-12-09 22:47:51

标签: python import

我正在研究paramiko包(forward.py)中的演示脚本,以熟悉Python中的SSH隧道。当我在IDE中打开演示脚本时,我注意到一些未使用的导入警告:

import getpass
import os        # <--- IDE warning: "'os' imported but unused"
import socket    # <--- IDE warning: "'socket' imported but unused"
import select
import SocketServer
import sys
from optparse import OptionParser

果然,脚本中没有明确引用任何模块。我是一个整洁的怪人,所以我想删除这种混乱 - 但我也缺乏经验,无法确定它们是否无关紧要。

对我来说,最直接的做法是删除导入,然后尝试在没有它们的情况下运行脚本,但我不知道我能够判断出是否因为我没有正常工作我仍然试图了解剧本的运作方式。

我发现a conversation让我觉得可能有理由在不使用它的情况下导入模块。但在investigating further中,在我看来,该对话中的示例与代码的功能无关,用户只是试图遵循风格约定。

如果从未引用任何导入的内容,如何才能证明导入的合理性?我猜可能有代码在导入时运行,例如:

"""
silly.py: this is very silly
"""

class ManBearPig(Man, Bear, Pig):
    def __init__(self, name):
        self.name = name

    @classmethod
    def summon(cls):
        """summon Gary"""
        global Gary
        Gary = cls('Gary')

ManBearPig.summon()

这似乎是一个可怕的想法,但我对我的python-fu确信不够充分。 socket已导入SocketServer,那么如果您没有明确使用它,那么在此处导入它的重点是什么?

2 个答案:

答案 0 :(得分:2)

是的,它足够安全,可以删除您的代码在当前模块中不使用的导入,或者本身没有副作用的导入。

Python导入模块一次并将它们存储在sys.modules中以供将来参考;后续导入将重新使用已导入的模块对象。有副作用的模块会使用它,但它们仍然必须一次导入。

对于“常规”模块,您只需要对模块对象或该模块中的对象进行额外引用。这需要一些额外的内存(除了模块对象本身),因此成本不是那么高。

但是,您必须跟踪您使用的模块,以及可能导致错误的代码中使用的全局名称。

答案 1 :(得分:2)

可以编写代码,其行为取决于模块是否已在此文件中导入 ,但IDE无法识别使用该模块:

if globals().get('socket'):
    do_the_right_thing()
else:
    do_something_subtly_different_that_is_hard_to_spot()

socket中导入SocketServersocket的名称空间中forward是否显示无效。

但是如果你认为脚本是合理的“正常”那么你可以安全地相信你的IDE代码是否使用了模块。或者您最终可以通过检查其代码来确认IDE的意见是否正确。

理论上还可以在其他地方使用其他脚本:

import forward
if hasattr(forward, 'socket'):
    good()
else:
    subtly_bad()

同样,这有点不正常,但是如果您的脚本forward由于某种原因选择记录它有一个名为socket的属性,那么删除该属性会破坏其已发布的界面。当然,IDE对forward的用户可能期望看到的内容一无所知。

请注意,当您第一次发现自己编写这样的代码时,您不能再认为自己的代码是“正常”的那一刻。所以尽量避免它: - )