How to run a Python project using __pycache__ folder?
compilation, cpython, pyc, python, python-3.x
Solution
You can enforce the same layout of pyc-files in the folders as in Python2 by using:
python3 -m compileall -b test3
The option `-b` triggers the output of `pyc`-files to their legacy-locations (i.e. the same as in Python2).
After that you can once again use the compiled cache via:
python3 main.pyc
The way the loading of modules works since PEP-3147, it is impossible to use pyc-files from `__pycache__` folder in the way you intend: If there is no `*.py`-file, the content of the `__pycache__` is never looked-up. Here is the most important part of the workflow:
import foo
|
|
-- > [foo.py exists?] --- NO ----> [foo.pyc exists?] -- NO --> [ImportError]
| |
| YES
YES |--> [load foo.pyc]
|
|-> [look up in __pycache__]
That means, files from `__pycache__` are only looked up, when a corresponding `*.py`-file can be found.
Obviously, building python scripts with a Python version 3.X in this way and trying to run the resulting pyc-files with another Python version 3.Y will not work: Different Python versions need different pyc-files, this is the whole point behind PEP-3147.
Problem
I want to run a Pythonic project using Python compilation (`.pyc` or `__pycache__`). In order to do that in Python2, I haven't any problem. Here is a simplified example in a Python2 project: Project tree: ``` test2 ├── main.py └── subfolder ├── __init__.py └── sub.py ``` Compile: ``` python -m compileall test2 ``` Project tree after the compile: ``` test2 ├── main.py ├── main.pyc └── subfolder ├── __init__.py ├── __init__.pyc ├── sub.py └── sub.pyc ``` As you can see, several `.pyc` manually generated. Now I can run this project using `main.pyc` as fine, which has a relation with the `sub.py`: ``` python main.pyc ``` Out: ``` Hi Bye ``` main.py content: ``` from subfolder import sub print('Bye') ``` sub.py content: ``` print('Hi') ``` Now I want to retry this behavior in a Python3 project. Here is a simplified `asyncio` (available in Python3) project: Project tree: ``` test3 ├── main.py └── subfolder ├── __init__.py └── sub.py ``` Compile: ``` python3 -m compileall test3 ``` Project tree after the compile: ``` test3 ├── main.py ├── __pycache__ │ └── main.cpython-36.pyc └── subfolder ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ └── sub.cpython-36.pyc └── sub.py ``` As you can see, `__pycache__` folders manually generated. But I cannot run this project using `main.cpython-36.pyc` which has a relation with `subfolder`: ``` cd test3/__pycache__ python3 main.cpython-36.pyc ``` Out (I expected that produced the `Hi Bye` message): ``` Traceback (most recent call last): File "test3/main.py", line 2, in <module> ModuleNotFoundError: No module named 'subfolder' ``` main.py content: ``` import asyncio from subfolder import sub async def myCoroutine(): print("Bye") def main(): loop = asyncio.get_event_loop() loop.run_until_complete(myCoroutine()) loop.close() main() ``` sub.py content: ``` print('Hi') ``` Question: How can I run this project (above Python3 project) using `__pycache__` folder? Or How can I run a Python3 project with the relation between subfolders using python compilation? [NOTE]: I cannot use the `python compileall` (Python2 compile) in the above `Python3` project due to the `asyncio` method. My Python(s) version is Python2.7 and Python3.6