V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
tukey
V2EX  ›  Python

[请教问题] 异常处理 finally 中的内容在 pycharm 编辑器中会报错,大神帮忙看下,多谢。

  •  
  •   tukey · 2018-07-29 16:45:28 +08:00 · 2516 次点击
    这是一个创建于 2311 天前的主题,其中的信息可能已经有所发展或是发生改变。
    def handle():
    ....try:
    ........f = open('./html/index.html', 'r')
    ....except IOError:
    ........s = 'xx'
    ........a = 11
    ....else:
    ........s = 'pp'
    ........a = 22
    ........f.close()
    ....finally:
    ........print(a)
    ........print(s)
    handle()

    问题:程序 finally 中的内容在 pycharm 编辑器中会报错 local variable 'a' referenced before assignment,但是执行没有问题。
    17 条回复    2018-07-30 17:33:11 +08:00
    billgreen1
        1
    billgreen1  
       2018-07-29 17:25:06 +08:00
    你这个程序,如果 try except 之间的代码比较多,出现 IOError 之外的,exception/error, 会出现什么情况?
    coffeSlider
        2
    coffeSlider  
       2018-07-29 17:28:53 +08:00 via Android
    英语水平为 0 啊
    zwh2698
        3
    zwh2698  
       2018-07-29 19:18:48 +08:00 via Android
    作用域是多大,考虑一下
    tukey
        4
    tukey  
    OP
       2018-07-29 20:13:08 +08:00
    @zwh2698 谢谢, 我把 finally 去掉,然后 finally 里的语句向前缩进 4 个空格,就不报错了。所以这两种情况对比,我就没搞懂。
    xenme
        5
    xenme  
       2018-07-29 20:22:38 +08:00 via iPhone
    楼上提到了作用域。
    如果在 as 前面抛异常了,那么 as 可能都没内容。所以会挂
    zhangpeter
        6
    zhangpeter  
       2018-07-30 07:03:33 +08:00
    else 和 finally 里不是同一个作用域,虽然语句缩进一样
    tukey
        7
    tukey  
    OP
       2018-07-30 08:52:38 +08:00
    @zhangpeter 但是这样就可以,他们作用域是一个吗?
    def handle():
    ....try:
    ........f = open('./html/index.html', 'r')
    ....except IOError:
    ........s = 'xx'
    ........a = 11
    ....else:
    ........s = 'pp'
    ........a = 22
    ........f.close()

    print(a)
    print(s)
    handle()
    atz
        8
    atz  
       2018-07-30 09:12:56 +08:00
    一般打开文件用 with open("xxxxxx") as f:
    guyskk0x0
        9
    guyskk0x0  
       2018-07-30 10:53:56 +08:00
    @tukey 1 楼已经解释清楚了,仔细看
    zhangpeter
        10
    zhangpeter  
       2018-07-30 11:18:59 +08:00
    推荐一篇讲作用域的文章,地址在 https://gist.github.com/zhang0peter/68208bc046db73ced8bc439006c7eb2a
    SimbaPeng
        11
    SimbaPeng  
       2018-07-30 11:54:51 +08:00
    楼上的真的会 Python 么?别在这里误人子弟了,try, except,else,finally 这些都不会产生新的作用域好吧。楼主的问题应该是出现了未捕获到的异常,导致 s 和 a 的赋值语句并未执行,然后 finally 里的异常会覆盖掉 try 里的异常。
    tukey
        12
    tukey  
    OP
       2018-07-30 15:03:02 +08:00
    @billgreen1
    @SimbaPeng
    感谢大家
    =====================
    你是说我可能 try...except 中语句多的话,有一个异常没有捕获到,导致我 except IOError 和 else 中两个分支中的语句都没有执行,那么 finally 中的变量我就没有定义了。如果是这样的话,那么为什么我 7 楼中的程序没有 pycharm 提示呢?因为如果有一个异常没有捕获导致变量未定义的话。
    =====================
    try...except/else...finally 我个人的理解是这样的,try 无论是否有异常,都会选择 except 或者 else 中的一个分支执行(如果异常我都捕获到了),然后再执行 finally,所以在 except 和 else 分支中我都对变量进行了赋值,在 finally 中应该不涉及到 pycharm 的提示信息“赋值前就引用变量”
    SimbaPeng
        13
    SimbaPeng  
       2018-07-30 15:15:56 +08:00
    @tukey 你 7 楼的程序打印的根本就不是函数里的变量,函数里的是局部变量,你下面 print 的是全局变量
    tukey
        14
    tukey  
    OP
       2018-07-30 15:22:41 +08:00
    @SimbaPeng 不好意思,程序是下面这样的,print(a)放在和 try 并列的位置,不是在函数外面。我在 pycharm 中可以运行且编辑器未提示报错。
    def handle():
    ....try:
    ........f = open('./html/index.html', 'r')
    ....except IOError:
    ........s = 'xx'
    ........a = 11
    ....else:
    ........s = 'pp'
    ........a = 22
    ........f.close()

    ....print(a)
    ....print(s)

    handle()
    SimbaPeng
        15
    SimbaPeng  
       2018-07-30 15:32:08 +08:00
    @tukey 你首先确定程序进了 except 还是 else,然后你用命令行去执行。
    aimiyooo
        16
    aimiyooo  
       2018-07-30 16:51:42 +08:00
    1 楼正解,出现了除 IOError 异常的其他异常。顺便说下最好使用 with as 语法,这样就不用 close 了。如果像楼主这样写的话,close 应该写在 finally 里面。
    tukey
        17
    tukey  
    OP
       2018-07-30 17:33:11 +08:00
    @aimiyooo close 写在 finally 里面编辑器会提示错误,我的理解是,如果打开文件有错误,那么引用 f = open()中的 f 是没有意义的,放在 finally 中 f 是一个无意义的量,没法关闭,因此要将 f.close()放在 else 中,打开文件没有报错那么引用 f 才需要关闭,打开失败的话就是没打开,不需要关闭。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5358 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 08:45 · PVG 16:45 · LAX 00:45 · JFK 03:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.