processes and threading files we handle this by reading each file in blockskeeping the previous block read to ensure that we don' miss cases when the only occurrence of the search word happens to fall across two blocks another benefit of reading in blocks is that if the search word appears early in the file we can finish with the file without having read everythingsince all we care about is whether the word is in the filenot where it appears within the file character encodings the files are read in binary modeso we must convert each block to string before we can search itsince the search word is string we have assumed that all the files use the utf- encodingbut this is most likely wrong in some cases more sophisticated program would try to determine the actual encoding and then close and reopen the file using the correct encoding as we noted in at least two python packages for automatically detecting file' encoding are available from the python package indexpypi python org/pypi (it might be tempting to decode the search word into bytes object and compare bytes with bytesbut that approach is not reliable since some characters have more than one valid utf- representation the subprocess module offers lot more functionality than we have needed to use hereincluding the ability to provide equivalents to shell backquotes and shell pipelinesand to the os system(and spawn functions in the next section we will see threaded version of the grepword- py program so that we can compare it with the parent-child processes one we will also look at more sophisticated threaded program that delegates work and then gathers the results together to have more control over how they are output using the threading module ||setting up two or more separate threads of execution in python is quite straightforward the complexity arises when we want separate threads to share data imagine that we have two threads sharing list one thread might start iterating over the list using for in and then somewhere in the middle another thread might delete some items in the list at best this will lead to obscure crashesat worst to incorrect results one common solution is to use some kind of locking mechanism for exampleone thread might acquire lock and then start iterating over the listany other thread will then be blocked by the lock in factthings are not quite as clean as this the relationship between lock and the data it is locking exists purely in our imagination if one thread acquires lock and second thread tries to acquire the same lockthe second thread will be blocked until the first releases the lock by putting access to shared data within the scope of acquired locks we can ensure that the shared data is accessed by only one thread at timeeven though the protection is indirect