我使用PyCharm在我的项目中移动文件,PyCharm将项目中的导入更新到新路径,这很棒。问题是,它还从这些文件中删除了未使用的导入。这对我来说是一个非常糟糕的行为,我找不到一种方法来阻止它。我不能检查它是否每次都这样做,因为有时它的数百个文件。
u3r8eeie1#
这是一个已知的问题:PY-54707。也在这个线程中讨论:here。您可以使用此选项来保护特定导入不被删除:
# noinspection PyUnresolvedReferences
字符串
fslejnso2#
一个未使用的导入应该是完全安全的,因为它 * 应该 * 没有任何影响。当我导入一个文件时,那里的代码正在执行,但PyCharm仍然认为它没有使用如果一个未使用的导入确实对你的程序产生了影响,那么你的代码结构就很糟糕。在Python中,导入不可能定义任何隐式全局变量或其他符号。作为对比,让我们看一些PHP代码:
<?php require_once 'foo.php'; $foo = new Foo;
字符串如果文件foo.php定义了Foo,那么在导入该文件时它将隐式可用。这不是Python的工作方式。Python只提供你显式import的名称。所以当你写:
foo.php
Foo
import
import foo
型.然后永远不引用foo,那么导入就不会被使用,而且它也不可能以某种方式被隐式地使用。所以唯一可能的方法是执行foo模块中的顶层代码,但由于该代码不能有任何全局效果(如定义“全局”类或其他东西),它唯一可能的效果是一些外部副作用,如写入文件或其他外部系统。(Let我们暂且不考虑这种可能性,即把注意力放在窗口之外并修改一些Python内部值(如sys.path);对于这类代码,有一个专门的地狱循环。所以我阅读字里行间的意思是,你把所有的代码都写成了跨几个文件的普通顶层代码,它都做了某种文件操作,你把它们导入到一行中来“编排”几个文件修改。例如:
foo
sys.path
a.py
with open(..., 'w') as f: f.write(...)
型
b.py
with open(..., 'w') as f: for i in range(...): f.write(...)
main.py
import a import b # end of file
型这不是你应该使用模块的方式。对于初学者来说,import系统是在假设模块只定义名称的情况下优化的。为实现这一点而执行的代码只是课程的一部分。如果你import同一个模块不止一次,代码只会执行一次,第一次导入模块时。因为模块定义的任何名称都应该是已知的,没有必要再做一次。import并不意味着“运行代码”,它的意思是“使此模块中的名称在我的模块中可用”。因为模块应该是这样工作的,所以对于使用您的代码的任何其他人来说,一个简单的import foo创建或修改任何外部资源都是非常令人惊讶的。你应该如何编写这样的代码:1.将任何副作用代码 Package 在函数中,如果需要,可以显式执行:
def create_data(): with open(..., 'w') as f: ...
型1.如果您希望能够将此文件作为独立脚本直接执行,请在底部添加此部分:
... if __name__ == '__main__': create_data()
型现在如果你直接从命令行运行这个文件,比如$ python a.py,它会执行create_data并像以前一样写入你的文件。但是,如果你从另一个文件中执行import,它就不会这样做了。1.当你想从另一个文件中编排代码时,import你需要的函数并显式调用它们:
$ python a.py
create_data
from a import create_data create_data()
型有了它,你甚至可以将多个函数放入同一个文件中,而不需要为每个任务单独创建一个文件。这很快就能实现更好的代码重用,从而缩短代码。有了它,你就走上了正确的道路,可以创建适当的复杂程序。PyCharm删除未使用的导入已经成为一个有争议的问题。
2条答案
按热度按时间u3r8eeie1#
这是一个已知的问题:PY-54707。也在这个线程中讨论:here。
您可以使用此选项来保护特定导入不被删除:
字符串
fslejnso2#
一个未使用的导入应该是完全安全的,因为它 * 应该 * 没有任何影响。
当我导入一个文件时,那里的代码正在执行,但PyCharm仍然认为它没有使用
如果一个未使用的导入确实对你的程序产生了影响,那么你的代码结构就很糟糕。
在Python中,导入不可能定义任何隐式全局变量或其他符号。作为对比,让我们看一些PHP代码:
字符串
如果文件
foo.php
定义了Foo
,那么在导入该文件时它将隐式可用。这不是Python的工作方式。Python只提供你显式
import
的名称。所以当你写:型
.然后永远不引用
foo
,那么导入就不会被使用,而且它也不可能以某种方式被隐式地使用。所以唯一可能的方法是执行
foo
模块中的顶层代码,但由于该代码不能有任何全局效果(如定义“全局”类或其他东西),它唯一可能的效果是一些外部副作用,如写入文件或其他外部系统。(Let我们暂且不考虑这种可能性,即把注意力放在窗口之外并修改一些Python内部值(如
sys.path
);对于这类代码,有一个专门的地狱循环。所以我阅读字里行间的意思是,你把所有的代码都写成了跨几个文件的普通顶层代码,它都做了某种文件操作,你把它们导入到一行中来“编排”几个文件修改。例如:
a.py
*型
b.py
*型
main.py
*型
这不是你应该使用模块的方式。对于初学者来说,
import
系统是在假设模块只定义名称的情况下优化的。为实现这一点而执行的代码只是课程的一部分。如果你import
同一个模块不止一次,代码只会执行一次,第一次导入模块时。因为模块定义的任何名称都应该是已知的,没有必要再做一次。import
并不意味着“运行代码”,它的意思是“使此模块中的名称在我的模块中可用”。因为模块应该是这样工作的,所以对于使用您的代码的任何其他人来说,一个简单的
import foo
创建或修改任何外部资源都是非常令人惊讶的。你应该如何编写这样的代码:
1.将任何副作用代码 Package 在函数中,如果需要,可以显式执行:
a.py
*型
1.如果您希望能够将此文件作为独立脚本直接执行,请在底部添加此部分:
a.py
*型
现在如果你直接从命令行运行这个文件,比如
$ python a.py
,它会执行create_data
并像以前一样写入你的文件。但是,如果你从另一个文件中执行import
,它就不会这样做了。1.当你想从另一个文件中编排代码时,
import
你需要的函数并显式调用它们:main.py
*型
有了它,你甚至可以将多个函数放入同一个文件中,而不需要为每个任务单独创建一个文件。这很快就能实现更好的代码重用,从而缩短代码。有了它,你就走上了正确的道路,可以创建适当的复杂程序。PyCharm删除未使用的导入已经成为一个有争议的问题。