multiprocessing - calling function with different input files
<p>I have a function which reads in a file, compares a record in that file to a record in another file and depending on a rule, appends a record from the file to one of two lists. </p>

<p>I have an empty list for adding matched results to:</p>

<pre><code>match = []
</code></pre>

<p>I have a list <code>restrictions</code> that I want to compare records in a series of files with.</p>

<p>I have a function for reading in the file I wish to see if contains any matches. If there is a match, I append the record to the <code>match</code> list.</p>

<pre><code>def link_match(file):
    links = json.load(file)
    for link in links:
        found = False
        try:
            for other_link in other_links:
                if link['data'] == other_link['data']:
                    match.append(link)
                    found = True
                else:
                    pass
        else:
            print "not found"
</code></pre>

<p>I have numerous files that I wish to compare and I thus wish to use the multiprocessing library. </p>

<p>I create a list of file names to act as function arguments:</p>

<pre><code>list_files=[]
for file in glob.glob("/path/*.json"):
    list_files.append(file)
</code></pre>

<p>I then use the <code>map</code> feature to call the function with the different input files:</p>

<pre><code>if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=6)
    pool.map(link_match,list_files)
    pool.close()
    pool.join()
</code></pre>

<p>CPU use goes through the roof and by adding in a print line to the function loop I can see that matches are being found and the function is behaving correctly. </p>

<p>However, the <code>match</code> results list remains empty. What am I doing wrong?</p>

<p><code>multiprocessing</code> runs a new instance of Python for each process in the pool - the context is empty (if you use <code>spawn</code> as a start method) or copied (if you use <code>fork</code>), plus copies of any arguments you pass in (either way), and from there they're all separate. If you want to pass data between branches, there's a few other ways to do it.</p>

<ol>
<li>Instead of writing to an internal list, write to a file and read from it later when you're done. The largest potential problem here is that only one thing can write to a file at a time, so either you make a lot of separate files (and have to read all of them afterwards) or they all block each other.</li>
<li>Continue with <code>multiprocessing</code>, but use a <a href="https://docs.python.org/3.5/library/multiprocessing.html#multiprocessing.Queue" rel="nofollow"><code>multiprocessing.Queue</code></a> instead of a list. This is an object provided specifically for your current use-case: Using multiple processes and needing to pass data between them. Assuming that you should indeed be using <code>multiprocessing</code> (that your situation wouldn't be better for <code>threading</code>, see below), this is probably your best option.</li>
<li>Instead of <code>multiprocessing</code>, use <a href="https://docs.python.org/3/library/threading.html#module-threading" rel="nofollow"><code>threading</code></a>. Separate threads all share a single environment. The biggest problems here are that Python only lets one thread actually run Python code at a time, per process. This is called the Global Interpreter Lock (GIL). <code>threading</code> is thus useful when the threads will be waiting on external processes (other programs, user input, reading or writing files), but if most of the time is spent in Python code, it actually takes longer (because it takes a little time to switch threads, and you're not doing anything to save time). This has its own <a href="https://docs.python.org/3/library/queue.html#module-queue" rel="nofollow"><code>queue</code></a>. You should probably use that rather than a plain list, if you use <code>threading</code> - otherwise there's the potential that two threads accessing the list at the same time interfere with each other, if it switches threads at the wrong time.</li>
</ol>

<p>Oh, by the way: If you do use threading, Python 3.2 and later has an improved implementation of the GIL, which seems like it at least has a good chance of helping. A lot of stuff for threading performance is very dependent on your hardware (number of CPU cores) and the exact tasks you're doing, though - probably best to try several ways and see what works for you.</p>

python multiprocessing