-2

Generating an MD5 checksum of a file

I have used one of the examples from the above link but made some a small change to it by removing the call to the function (originally from above):

import hashlib
hash = hashlib.md5()
with open('validFilePath/file.xxx', "r+b") as f:
    for block in iter(lambda: f.read(65536), ""):
        hash.update(block)
return hash.hexdigest()

This gives me the following error.

File "<string>", line 4, in <module>
TypeError: 'function' object is not iterable

Am I missing some basic Python premise?

Community
  • 1
  • 1
  • 3
    @jonrsharpe: and that is a valid use of `iter()`, see [What's perfect counterpart in Python for "while not eof"](https://stackoverflow.com/a/15599648) for another example of passing a callable to `iter()`. – Martijn Pieters Apr 29 '15 at 21:30
  • 1
    Post your actual code, specially line 4. – Ashwini Chaudhary Apr 29 '15 at 21:30
  • Can you post your actual code? – Padraic Cunningham Apr 29 '15 at 21:32
  • 1
    Are you *sure* you have the second argument to `iter()`? I can reproduce your error message by using `iter(lambda: f.read(65536))`, for example. – Martijn Pieters Apr 29 '15 at 21:34
  • @Padraic How do I keep the returns? This is my actual code: python -c "import hashlib hash = hashlib.md5() with open('/Volumes/Macintosh HD/AF 1/bbb.def', 'r+b') as f: for block in iter(lambda: f.read(65536), ""): hash.update(block) print hash.hexdigest()" – Keith Proctor Apr 29 '15 at 21:48

2 Answers2

2

You are almost certainly missing the second argument to the iter() function.

Without the second argument the first argument must be iterable, but a lambda produces a function, and that's not an iterable:

>>> iter(lambda: f.read(65536))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'function' object is not iterable

From the iter() documentation:

The first argument is interpreted very differently depending on the presence of the second argument. Without a second argument, o must be a collection object which supports the iteration protocol (the __iter__() method), or it must support the sequence protocol (the __getitem__() method with integer arguments starting at 0). If it does not support either of those protocols, TypeError is raised.

With the second argument there you get a proper iterator for the for loop to iterate over:

>>> iter(lambda: f.read(65536), '')
<callable-iterator object at 0x100563150>

Each iteration the lambda function is called, until that function returns '', the empty string. In other words, 64Kb is read each iteration, until the end of the file is reached, at which point the f.read() operation returns an empty string and the iterator raises StopIteration.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
-1

Thanks ... figured it out with Martins help. Thanks for pointing out the reason for the error. For some reason it didn't like the double quotes provided in the second parameter of the iter function. I changed those to single quotes and the function works now.

-keith

  • 2
    That should make no difference unless you are actually trying to run it as you posted in a comment. There is no difference between `"` and `'` in python, you also cannot return outside a function – Padraic Cunningham Apr 29 '15 at 21:58
  • Yep... that is how I'm running it. I'm in FileMaker Server SQA and I'm sending a small dynamic python command from a control box to a test box. Most of the commands are 1 or 2 lines of python. The commands do operations such as getChecksum, copyFile, addRecord, deleteRecord, recordExists. This is extremely useful for my testing. So what is the difference between " and ' when running via the command line. I thought I had protected the quotes correctly by escaping the quote and saw the double quote on the remote machine. – Keith Proctor Apr 29 '15 at 23:23