Pythonic方式编写打开成功的if条件语句

13

我正在寻找使用Python的方法来创建并写入文件,如果成功打开文件则进行操作,否则返回错误(例如权限被拒绝)。

我在这里阅读了这篇文章What's the pythonic way of conditional variable initialization?。虽然我不确定这种方法是否可行,因为我已经尝试过测试它。

os.write(fd,String) if (fd = os.open(str("/var/www/file.js"),os.O_RDWR)) else return HttpResponse("error on write")

它应该只是一行代码。

当我执行上述操作时,我会遇到如下的语法错误:

    os.write(fd,String) if (fd = os.open(str("/var/www/file.js"),os.O_RDWR)) else return HttpResponse("error on write")
                               ^
SyntaxError: invalid syntax `

有没有更加pythonic的一行或两行代码可以实现这个目的?


1
Python三元操作符是value1 if condition else value2,而不是statement1 if condition else statement2。返回语句不是一个值,因此不能在三元操作符中使用。 - khelwood
使用with语句。 - PM 2Ring
也许只需要使用 try: with open(...) except: print("跳过并失败。无怨无悔!"),除非你只想寻找三元运算符的解决方案。 - jDo
4个回答

24
try:
  with open('filename.ext', 'w+') as f:
    f.write("Hello world!")
except IOError as e:
  # print("Couldn't open or write to file (%s)." % e) # python 2
  print(f"Couldn't write to file ({e})") # py3 f-strings

感谢您的输入,我将与评论一起进行编辑!

2022/03 - f-strings 的编辑


8
啊!不要使用裸露的 except: 语句!如果你想捕获所有异常,请改用 except Exception:。但是,如果你只是想使用 with 来管理文件上下文,那么做得非常好。 - PaulMcG
5
那应该是 IOError,如果我没记错的话。你不应该捕获所有异常,只捕获你想要的那个。 - L3viathan
2
你应该更加明确地表达你的异常信息。在这种情况下,它应该是 IOError 异常。将其保留在基本的“Exception”中并不是最好的选择。 - idjaw
1
所以我知道with执行了open的__enter____exit__方法。但是,为什么它比仅使用try: f = open('filename.txt', 'w+') f.write("hello world") except IOError as e...更好呢?因为异常已经被捕获并清理了。open的__enter____exit__方法有重要的作用吗?此外,我一直看到上下文管理器这个词,那是什么?不想在不理解的情况下使用它 :)。 - dylan7
3
open 函数作为上下文管理器,在进入和退出时会执行一些操作。对于 open 函数来说,重要的是它在 __exit__ 方法中所做的事情——关闭文件。 - L3viathan

4

不要嵌套try和with语句(如果内部代码引发了IOError,则会错过它),我强烈建议使用这种语法。它减少了一层嵌套,并确保由于打开文件时引发了IOError。这样,您就不会捕获不需要的异常,而且有更多的控制。

f = None
try:
    f = open('file', 'w+')
except IOError:
    print("Couldn't open the file")
else:
    f.write('You are opened')
finally:
    if f: f.close()

没有真正的Pythonic方法可以做到一行代码,而且通常最好避免过长的一行代码。


我认为这是有问题的。在一个小问题上,你的print语句将原因说明为“打开或写入”,但实际上只是打开。更根本的是,open可能会成功,但write可能会失败。最后,如果需要显式关闭,使用with(在try内部)会更好。 - Ami Tavory
@AmiTavory 谢谢,已修复。关于写入,写入失败和打开失败是两回事。在 try 内使用 with 会使错误难以分离,你不觉得吗? - Bharel
不是很喜欢它,但也许这只是个人口味问题。我会点赞的,因为它提出了一些与其他答案不同的考虑因素。 - Ami Tavory

3

由于您询问了Pythonic的做事方式,我认为您应该考虑先行执行再征求谅解的理念。也就是说,直接执行操作,如果出现问题则捕获相应的异常。

例如,

In [1]: open('/usr/tmp.txt', 'w').write('hello')
---------------------------------------------------------------------------
IOError                                   Traceback (most recent call last)
<ipython-input-1-cc55d7c8e6f9> in <module>()
----> 1 open('/usr/tmp.txt', 'w').write('hello')

IOError: [Errno 13] Permission denied: '/usr/tmp.txt'

如果没有执行操作的权限,将抛出一个IOError错误。只需捕获它即可。
try:
    open('/usr/tmp.txt', 'w').write('hello')
except IOError:
    ...

亚历克斯·马特利曾经谈到过这个问题,并描述了一些关于检查权限的固有谬误。在这些事情中存在本质上的竞争。当您打开文件时,您可能始终具有写入权限,但稍后在尝试写入时则可能没有权限。无论如何,您都必须处理异常,因此最好直接构建它们。

3
如果您想成为Pythonic,设计代码时始终注重可读性。老实说,在try/except中包装某些内容并相应地控制逻辑完全没有问题。

又称EAFP——容易请求宽恕比征得许可更容易。

此外,当您写入文件时,最好使用上下文管理器。

因此,这可以轻松转化为以下内容:

try:
    with open('your_file', 'w') as f:
        f.write(your_data)
except (OSError, IOError) as exc:
    print("Your file could not be written to, your exception details are: {}".format(exc))

把 try 放在 with 里面不是更符合 Python 的风格吗? - B. M.
@B.M. 如果那个文件不存在会发生什么?它会引发异常。不过你提到的一件事情是,如果出现这种情况,会引发一个FileNotFoundError异常。所以你需要捕获这个异常和IOError异常。 - idjaw
谢谢,已经理解。在我看来,对于编写而言,FileNotFoundError是不可能的,因为文件并不存在。然而,open(1, 'w')会引发一个OSerror。 - B. M.
FileNotFoundError是从OSError派生的:class FileNotFoundError(OSError):。然而,对于可能出现的任何其他类型的OSError,最好获得OSError。 - idjaw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接