【python】(异常)常见异常合集 | SyntaxError: invalid syntax;Missing parentheses in call to ‘print‘;LookupError

常见异常合集 - 写给完全python小白的用户

内容说明
这一篇博客是最简单的异常情况,基本上是发生在脚本“编译成字节码”过程中就抛出异常的情况。
(大部分都是语法问题)

本文背景
我个人目前是不需要这东西啦。
但是像我自己也是其它领域(比如其它编程语言)的小白
(比如 前端(bootstrap),node.js 和 其它等等 )。
偶尔就会需要用到其它的编程语言来做事情,但是拿到的,搜到的资料中的代码可能并没有经过严格的测试之后贴上去(我个人偶尔也会按思路简要写些代码贴出来,不过没有测试运行过,测试过我一般会说明,不然既是 CV 即用的),所以照抄运行就会有一些低级错误发生。

但是正如我说的,有时候不得不使用到其它编程语言,但是又不会一直在用那门语言,只是一部分需要用到,这样去学一整门语言的语法等等成本还是有点高的。

所以我个人乐见大家用 Python 来实现一些东西,即使不懂 python,只是临时用一下也 OK。

这篇 blog 就来提供你们可能遇到的一些很通常的,常见的问题的原因和解决方式。

本博客不定期更新,欢迎在评论区贴出你们的问题,在我知道原因和答案的情况下就会解答,并且可能加入成为本文的一部分

希望本文在未来能够囊括一切 Python 的基本异常问题,
希望你想要解决的基本异常问题都能在本文找到。

基本语法异常

缩进对齐 - IndentationError: unexpected indent

这个没什么好说的,所有的 Python 文件都应该严格按照一致的对齐。
下面是 foo 函数第一个中第一行内容三个空格,第二行内容四个空格造成的没有对齐异常。
第二个 foo 函数修正了这个问题,所以运行的时候就没有异常现象发生。
缩进对齐异常现象复制

不要去探究哪一段对齐和哪一段缩进长度不同似乎也可以运行。
所有 python 文件都对齐,以及缩进建议统一都是四个空格,这样即可。

另外,不要在一个文件中 TAB 和 Space(空格)混用。
统一所有 python 文件都使用 Space 来缩进
(你可能喜欢 TAB,我个人原本就是 TAB 的忠实拥护着,但是 PEP81 建议使用空格;
好吧,那就使用空格吧,我不是一个固执的人。遵循一定的(合理的)规范可以让我们的生活更美好)

如何将一个文件中的所有 TAB “一下子”全部自动转换为四个空格?
现在的编辑器一般都支持这个功能,只是需要你根据你使用的编辑器去找一下这个功能在哪里而已,
比如 Sublime Text:
convert tab to space

函数参数:SyntaxError: positional argument follows keyword argument

函数参数在传递 keyword 的时候,必须在没有 keyword 的后面。

TODO update me



版本语法异常

Python3.x 的版本在语法上做了相当大的改动。很多 Python2 版本的代码没有修改一般都会报一些错误。
但是还好,大部分代码都能改改常见的地方就能在 python 3 中运行。
而对于移植难度很大的代码,个人建议不如直接用 python 2 解释器运行。
(如果有修改和定制的需要,你已经脱离了本文面向的读者群,这里提供一个使用进程间通信来使用 python 2 代码的建议。相信你会知道如何写 Python 的进程间通信的。)

表达式改为函数造成的一系列异常

如果不明白标题没有关系,看到标题留个印象;未来有意学习 Python 的时候,你就有了看到类似名词的实例场景;有助于将概念和实例/应用结合起来理解。

找到你对应的异常,对上号,按 solution 修改一下,即可。

python2 和 python3 print 不同造成的异常

在 Python 2 中,print 是一个“表达式”,在 Python 3 中,print 是一个函数。
所以将 print 改成函数形式即可:

复制 print 语法异常(SyntaxError) 现象

print 该为函数问题

  File "<ipython-input-2-20f88f935616>", line 5
    print "IndexError: ", e
                       ^
SyntaxError: Missing parentheses in call to 'print'
solution

改成函数形式的意思就是 print() 👈 这么使用 print 即可。

try:
    raise IndexError("out of range")
except IndexError as e:
    print("IndexError: ", e)

运行的到预期输出:
python print 版本问题 - solution 运行输出

raise 语法变化后的异常

虽然这个问题本质上不适合放在 “表达式改为函数造成的一系列异常” 这个标题下,
但是因为和 print 的代码写法形式很相像,并且上一节刚好使用到了它,
所以将这个问题放在这个位置。

可能有部分读者发现了:

N/A

上面“复制现象”中的 raise IndexError("out of range") 和手上的代码长的不太一样。

上面的 raise IndexError("out of range") 写法在 Python 2 中也是正确的!!!

复制 raise 语法变化后的问题现象

如果你使用的是一份 Python 2 的源码,那么它可能更像这么编写:

try:
    # ...run many things...
    _var = []  # consider "[]" as a function to return a list
    if not _var:
        del _var
        raise RuntimeError, "no result"
except RuntimeError as e:
    print "RuntimeError", e
    raise
else:
    pass # ... more code, deal with "_var"...

正如我所说的,这是一份 Python 2 的代码,所以我将 line 8 按照 Python 2 的语法书写。

当然,这段代码在 Python 2 的解释器中是可以正常运行的。 它会抛出一个 RuntimeError 而非语法错误。

在 Python 3 的解释器中运行:

  File "<ipython-input-13-0b37b768c203>", line 6
    raise RuntimeError, "no result"
                      ^
SyntaxError: invalid syntax

和预期的一样,它给出了一个语法错误: SyntaxError: invalid syntax

Solution

“异常” 都是“类”,raise 语法的行为是抛出异常的实例。
所以不要使用 , 的写法,像前面的显式地实例化异常类,然后抛出即可:

try:
    # ...run many things...
    _var = []  # consider "[]" as a function to return a list
    if not _var:
        del _var
        raise RuntimeError("no result")
except RuntimeError as e:
    print ("RuntimeError", e)
    raise
else:
    pass # ... more code, deal with "_var"...

修改(line 6 和 line 8)后的运行结果:
N/A

注意,这个异常是正确的行为。因为它已经不是语法错误了。

注意到上面运行结果的截图中,有 ”RuntimeError no result“ 这一行输出,
这是在 line 7 捕获异常之后,line 8 的输出。
之后这段代码又将这个异常继续抛出。
所以修改之后的代码行为和预期一致。

对于本文给出的该段 demo 程序,你可以修改 line 3,使 _var = [1, 2, 3, ],只要列表不为空就可以。

然后运行一下,这样就不会抛出 RuntimeError 了。

Windows CMD 中运行 Python 解释器出现 LookupError: unknown encoding: 问题

CMD 中,cp65001 对应 UTF-8 编码,而 cp936 对应 GBK (gbk2312) 编码。

现象

Microsoft Windows [Version 10.0.17134.472]
(c) 2018 Microsoft Corporation。保留所有权利。

C:\Users\joseph>python2
Python 2.7.12 (v2.7.12:d3...) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

LookupError: unknown encoding: cp65001
>>> import sys

LookupError: unknown encoding: cp65001
>>>

Solution

Microsoft Windows [Version 10.0.17134.472]
(c) 2018 Microsoft Corporation。保留所有权利。

C:\Users\joseph>chcp 936

活动代码页: 936

C:\Users\joseph>
C:\Users\joseph>
C:\Users\joseph>python2
Python 2.7.12 (v2.7.12:d33...) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> # -*- coding: utf-8 -*-
...
>>> import sys
>>>

Reference: [python] 命令行模式下出现cp65001异常

“奇异”现象(和预期不符的现象)

print() 不输出,在程序结束(Ctrl+C)时大块输出

你可能使用了 end=""; 同时程序中没有其它地方使用 print() 并且没有end='';
这是因为解释器会默认会等待有“一行”的时候再输出。

产生该现象的代码可能像这样:

def main():
    i = 0
    from time import sleep
    while True:
        print(i, "; ", end="", )
        i += 1

        sleep(1)  # 这里使用 sleep 表示其它耗时的运算(即其它耗时代码在运行)

if __name__ == "__main__":
    main()

你可能预期它的输出像这样:
print_with_end=_and_with_flush

但是它却像这样:

运行时不输出,结束程序时大块输出的现象

print_with_end=_but_no_flush

solution

问题的关键在与 python 解释器的行为,在输出的时候,它会等待出现 “\n” 换行符之后输出;
即,如果将上面代码换成 print(i, "; \n", end="") 就会马上输出。

当然,这应该不是你想要的,因为你就是希望不要换行,才使用了 end=""
所以,既然知道了原因,那么就要了解一下 print 函数的另外一个可选参数 flush 了。
它表示清空“输出缓存”(它用在 print 里面,当然既是“输出”的缓存)。默认情况下,它是 flush=False

所以这种情况下,只要将

print(i, "; ", end="")

换成

print(i, "; ", end="", flush=True)

这样即可!

Note: 更多 Python 程序上的基础问题(非代码本身bug)收集补充中…

加入本文的编辑?

在 GitHub 上 fork 这个地址 🔗

修改 Python 目录下的
[本文]: 【python】(异常)参见异常合集 - 写给完全python小白用户.md

然后push 到你自己的 fork 仓库上,最后向我发起 pull request 即可

你也可以在 GitHub 上的 issue 板块贴出你遇到的问题

issue 板块跳转 链接🔗


  1. PEP8: 一种 Python 编程的“规范”定义。详细规定的 python 程序应该如何缩进,每行长度应该多长等等。 ↩︎

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值