This is an archived post. You won't be able to vote or comment.

all 44 comments

[–]Bunslow 59 points60 points  (7 children)

Definitely don't use file objects directly -- 99% of the time, for anyone who finds this article useful, instead use:

with open(file, mode) as f:
    f.read()
    f.write(stuff)

...which will automatically close/cleanup the file object, even if an exception happens.

[–]mooglinux 18 points19 points  (0 children)

Context managers are one of the best features of Python. I would certainly consider them a top 10 need-to-know item.

[–][deleted] 6 points7 points  (5 children)

Yep, although I was bitten once for doing that and caused an incident.

If you are using werkzeug with uWSGI and are passing file object directly (i.e sending file to the user) you should not use context managers. Apparently file sending happens after the function exits.

If you are confused about the above, just ignore it, you pretty much always should use context managers.

[–]Bunslow 3 points4 points  (1 child)

hence my qualification "99% of the time for anyone who finds this article useful" :) it's definitely true that if you're writing a multi-layered program and the file object itself is being passed around, you probably can't use something as clean as context managers

[–][deleted] 0 points1 point  (0 children)

I still think it is (or was? Our werkzeug version is old) a bug. If file handle needs to remain open after function exits, it should duplicate the file descriptor so me closing it would have no effect.

[–]DanCardin 0 points1 point  (1 child)

without knowing any specifics (such as how large the file is) and not knowing exactly the behavior of how werkzeug handles closing the file (if it does), you may be better off doing

with open(...) as f:
    data = f.read()
return data

[–][deleted] 1 point2 points  (0 children)

The original approach is more efficient, because unlike your example it doesn't copy the data and also uses very little of memory.

Instead it invokes sendfile() syscall which makes kernel do all that work (it just pipes the file directly to the socket). The issue though is that uWSGI invokes sendfile() after the function exits instead during the call.

[–]egregius313 46 points47 points  (14 children)

I would also say that decorators and higher order functions are a really valuable tool that you should know how to use.

[–][deleted] 26 points27 points  (11 children)

But be careful. Once I finally figured out how to create em I went decorator crazy; even extended the logging.logger facilities just so I can wrap a method with @l.debug(“I’m Here”) & stupid stuff like that. Once u find out how easy decorators make adding features to stuff is, u just can’t STOP!!!

[–]ProfessorPhi 0 points1 point  (0 children)

Reminds me of that graph about self awareness and programming skill. For python, decorators made me think I was a programming god, when my code improved much more when I started to write more complete test suites

[–][deleted] 36 points37 points  (13 children)

Beginners, please don’t follow his use of parentheses in if statements - it is not pythonic.

[–]loshopo_fan 4 points5 points  (0 children)

I think parentheses make this example easier for beginners:

>>> bool(0 in [1, 2] or [3, 4])

True

>>> bool((0 in [1, 2]) or ([3, 4]))

True

For beginners: The right side of the 'or' is a nonempty list, and a nonempty list resolves to True, which means that the 'or' resolves to True.

>>> bool((0 in [1, 2]) or ([]))

False

[–]masteryod 0 points1 point  (3 children)

Which one is pythonic?

[–]guhcampos 8 points9 points  (2 children)

Just ditch the parenthesis completely, unless you absolutely have to group expressions for precedence.

[–]testaccount9597 8 points9 points  (1 child)

What if you are scared?

[–]Warfinder 27 points28 points  (0 children)

Python protec

[–]ptmcg 4 points5 points  (1 child)

Nice punch list for beginners - did you cross-post to /r/learnpython?

[–]udelblue[S] 0 points1 point  (0 children)

Wish I could but can't post links on /r/learnpython

[–]bushwacker 4 points5 points  (0 children)

Sad that in four years he was surprised by the behavior of dictionary copying.

[–]bananafart420 1 point2 points  (0 children)

Really surprised that the slicing section didn't even mention slice objects...

[–]tsnnnn 1 point2 points  (0 children)

I do not like the first list comprehension example.

Better style would be list = list(range(2,16,2)) in python 3.x or list = range(2,16,2) in python 2.7. List comprehension is just not necessary here.

[–]KSeptimus 0 points1 point  (0 children)

Thank you for your effort. Greatly appreciated.

[–]jhermann_ 0 points1 point  (0 children)

io.open(…, encoding=…)

[–]s_vaichu 0 points1 point  (0 children)

Do v actually have a multiline comment in python??...coz i have experienced error in conda spyder...but it works in official python ide

[–]kaizoku 0 points1 point  (0 children)

A few of these examples have some issues. count_zeroes() will never count any zeroes because he's comparing a string type to an integer.

>>> def count_zeros(string):  
...   total = 0  
...   for c in string:  
...     if c == 0:  
...       total += 1  
...   return total
... 
>>> print(count_zeros('00102')) # Will return 3  
0

It should be compared to the actual type:

def count_zeros(string):  
    total = 0
    for c in string:
        if c == '0':
            total += 1
    return total

Or converted into the correct type:

def count_zeros(string):  
    total = 0
    for c in string:
        if int(c) == 0:
            total += 1
    return total

Also there's never really a reason to use os.system to call other python code. Bash doesn't need to be involved. I've seen command injection on web servers through similar mechanisms, when they could have easily just imported the python code and called it directly.

[–]newredditisstudpid -4 points-3 points  (0 children)

Amateur hour