Hi Christian (2022.03.07_11:06:03_-0400)
> Maybe there's a potential race while zipimporting modules, that one
> doesn't see with regular imports? Or I'd assume upstream would have run
> into this bug by now. I marked the fixed version based on the zipimport
> hunch.

Yes, there is. And it has already been fixed in Python 3.10, as part of
https://bugs.python.org/issue42131

Reproducer attached.

SR

-- 
Stefano Rivera
  http://tumbleweed.org.za/
  +1 415 683 3272
#!/usr/bin/env python3

import argparse
import sys
import tempfile
import threading
import time
import zipfile


SLOWIMPORT = """
import time

def prepare():
    time.sleep(1)
    return 'complete'

status = prepare()
"""


class Monitor(threading.Thread):
    def run(self):
        global success
        for i in range(12):
            if 'slowimport' in sys.modules:
                import slowimport
                assert hasattr(slowimport, 'status')
                success = True
                print('Monitor:', slowimport.status)
                return
            time.sleep(0.1)


def reproduce():
    global success
    sys.modules.pop('slowimport', None)
    success = False
    m = Monitor()
    m.start()
    import slowimport
    print(slowimport.status)
    m.join()
    return success


def main():
    p = argparse.ArgumentParser()
    p.add_argument('--zip', action='store_true')
    p.add_argument('--py', action='store_true')
    args = p.parse_args()
    if args.zip:
        with tempfile.NamedTemporaryFile(prefix='slowimport', suffix='.zip') as f:
            with zipfile.ZipFile(f, 'w') as z:
                z.writestr('slowimport.py', SLOWIMPORT)
            f.flush()
            sys.path.append(f.name)
            r = reproduce()
    elif args.py:
        with tempfile.TemporaryDirectory(prefix='slowimport') as tempdir:
            with open(f'{tempdir}/slowimport.py', 'w') as f:
                f.write(SLOWIMPORT)
            sys.path.append(tempdir)
            r = reproduce()
    else:
        p.error('One of --zip or --py is required.')
    if not r:
        sys.exit(1)


if __name__ == '__main__':
    main()

Reply via email to