问 2 个关于 Python 的简单问题。困扰我很久 - V2EX
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
northisland
V2EX    Python

问 2 个关于 Python 的简单问题。困扰我很久

  •  1
     
  •   northisland 2017-10-17 15:32:11 +08:00 5214 次点击
    这是一个创建于 2946 天前的主题,其中的信息可能已经有所发展或是发生改变。

    操作 json 文件相关的。

    我要读文件进来,

    第一种写法

    json_obj=None with open(path) as f: json_obj=json.loads(f.read()) 

    第二种写法

    json_obj=json.loads(open(path).read()) 

    问题 1:

    第一种写法里,第一行能否删掉?

    换言之,就是 with 里的变量 json_obj 能否自动 with 在这个过程后存在?

    问题 2:

    第二种写法,是否正确?临时变量 open(path)在结束时,是否释放了文件句柄?

    提前谢谢各位帮助答疑解惑

    25 条回复    2017-10-26 17:58:41 +08:00
    WhoAmI233
        1
    WhoAmI233  
       2017-10-17 15:40:17 +08:00   1
    第一种写法第一行不能删,第二种写法正确的,open(path)在结束时肯定释放了。
    whx20202
        2
    whx20202  
       2017-10-17 15:46:56 +08:00
    第一种为什么不能删啊
    WhoAmI233
        3
    WhoAmI233  
       2017-10-17 15:48:10 +08:00
    @whx20202 删了,那你定义这个变量有何作用啊?思考一下变量的作用域
    mgna17
        4
    mgna17  
       2017-10-17 15:49:09 +08:00
    第一种:第一行可以删,with 中用到的变量在退出 with 之后可以继续使用

    第二种:python3 的文件对象有个 __del__ 函数,应该会自动释放的。python2 没有这个 __del__ 函数,不清楚
    XIVN1987
        5
    XIVN1987  
       2017-10-17 15:51:37 +08:00
    json_obj=None 可以删掉

    第二个问题文件应该不会被自动 close(),我试了在 ipython 命令行中执行 open('test.txt'),然后去删除 test.txt ,,系统报错说 test.txt 文件已经被打开了,,不让删除,,所以应该在你的软件执行完退出后文件句柄才能被释放
    ChristopherWu
        6
    ChristopherWu  
       2017-10-17 15:54:07 +08:00
    其实,第一行可以删。
    不过加了 json_obj=None, 是保证代码即便出现错误时,json_obj 也会有初始值。
    Yinz
        7
    Yinz  
       2017-10-17 15:54:28 +08:00   1
    第一种,可以删掉第一行。
    第二种,以前写爬虫的时候试过这么写然后跑光了句柄,程序卡死,但是不记得当时是用的 PY2 还是 PY3 了
    XIVN1987
        8
    XIVN1987  
       2017-10-17 15:57:05 +08:00
    更正下,,刚才说错了

    如果是在函数内打开的文件,比如
    def test(): open('test.txt')

    在命令行中执行 test()

    之后可以立即在文件浏览器中删掉 test.txt 这个文件,,

    说明函数退出后文件句柄就被释放了
    justou
        9
    justou  
       2017-10-17 15:57:24 +08:00
    with 是上下文管理器语法, 它保证它经手的资源在退出 with 块后被正确释放, 即使发生了异常.

    如果没有发生异常, 第一种情形可以不用 json_obj=None, 退出 with 块后 json_obj 继续存在;

    如果发生了异常, 第一种情形 json_obj 未定义, 但是文件会被正确关闭. 但是第二种情形文件不会被正确关闭(json_obj 同样未定义), 直到程序结束.
    BBCCBB
        10
    BBCCBB  
       2017-10-17 16:00:14 +08:00
    第一行那个可以删, Python 作用域和其他的不太同, 和 js 的很像,

    我也不知道第二种对不对, 也不想尝试... 推荐使用 with, 显示释放
    tamlok
        11
    tamlok  
       2017-10-17 16:04:42 +08:00 via Android   1
    标题写法应该是“两”,不是“ 2 ”
    ChristopherWu
        12
    ChristopherWu  
       2017-10-17 16:06:39 +08:00   1
    第二种严格来说可以不关掉。
    可以自己测试一下:
    ```
    import json
    # json_obj=None
    json_obj=json.loads(open("/Users/yonghaohu/a").read())
    open("/Users/yonghaohu/te/a")
    while(1):
    pass
    ```

    运行程序后,lsof -p 该程序, 查看打开的文件, 是没有打开任何 a 文件的。

    如果你在 while 里, 不断调用 open,lsof -p 则会看到该文件。

    Python 85861 yonghaohu 3r REG 1,4 7 108089581 /Users/yonghaohu/te/a
    ChristopherWu
        13
    ChristopherWu  
       2017-10-17 16:18:49 +08:00
    接上,gc 删掉打开的文件对象时, 会自动删掉掉句柄。但是这个过程是不可控的,最好还是自己手动 close
    SuperMild
        14
    SuperMild  
       2017-10-17 16:21:02 +08:00   1
    不懂 python,但是,不是自己实际测试一下就能确定吗?
    akiakiseofficial
        15
    akiakiseofficial  
       2017-10-17 16:27:40 +08:00 via iPhone   1
    第一行可以删,with 块跟函数和模块不同,没有定义新作用域。
    第二个临时变量在语句结束时丢失引用被垃圾回收,CPython 和 IPython 会刷新并且关闭文件。而 PyPy 和 JPython 采用不同的垃圾回收机制所以会有不同的情况出现。
    虽然 CPython/IPython 会在文件对象丢失引用时刷新并关闭,还是推荐使用 with 语句。
    这两个问题我记得 流畅的 Python ( fluent python ) 上都有简单的提到,这本书真的太好了。
    enenaaa
        16
    enenaaa  
       2017-10-17 16:38:23 +08:00
    @justou 第 2 种写法里,如果发生异常。 并不是直到程序结束才释放, 而是直到该异常被处理后才释放。
    刚刚试过。
    dongxiaozhuo
        17
    dongxiaozhuo  
       2017-10-17 16:41:01 +08:00 via iPhone
    py2 的话,第一种情况,第一行可以删除。不过为啥不用 json.load 方法,直接读取文件对象,不是更好?
    strahe
        18
    strahe  
       2017-10-17 17:07:17 +08:00   1
    一楼瞎说, 1, 第一行可以删, 而且建议删,
    第二种不建议这么写, open 以后要主动 close
    stebest
        19
    stebest  
       2017-10-17 17:10:24 +08:00
    同认为第一行可以删,Python 不需要预先定义。
    oroge
        20
    oroge  
       2017-10-17 17:23:00 +08:00 via iPhone
    https://stackoverflow.com/questions/38660609/when-how-does-an-anonymous-file-object-close

    上面说“测试一下不就行了”的人不怕遇到 undefined behavior ?
    linuxchild
        21
    linuxchild  
       2017-10-17 17:31:44 +08:00
    with 就是用来自动释放的 - -。没有 with 咋个释放
    zmj1316
        22
    zmj1316  
       2017-10-17 18:25:08 +08:00 via Android
    GC 的时候会 close 掉的
    honmaple
        23
    honmaple  
       2017-10-18 09:39:57 +08:00
    第一种第行肯定可以删,假设 with 语句出错了,想要捕捉错误可以用 try...except,json_obj 就可以另外定义到 except 里,如果 with 出错了不捕捉,预先定义好的 json_obj 又有什么用
    siteshen
        24
    siteshen  
       2017-10-19 13:03:55 +08:00
    1. 不知道是否可以删。我的建议是不要删,这样就不用关心 with 的作用域的问题;
    2. open(path).read() 肯定不会自动 close 文件,和 python 哲学 "Explicit is better than implicit" 冲突。

    ps: 可以使用函数 `json.load` 少敲几个字符。
    wangdaqiao
        25
    wangdaqiao  
       2017-10-26 17:58:41 +08:00   1
    第一种,可以简化一点点

    with open(path) as f:
    json_obj=json.load(f)
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1290 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 17:07 PVG 01:07 LAX 09:07 JFK 12:07
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86