Как запустить проект Python, используя папку __pycache__?

Я хочу запустить проект Pythonic, используя компиляцию Python (.pyc или же __pycache__). Для того, чтобы сделать это в Python2, у меня нет никаких проблем.


Вот упрощенный пример в проекте Python2:

  • Дерево проекта:

    test2
    ├── main.py
    └── subfolder
        ├── __init__.py
        └── sub.py
    
  • Обобщение:

    python -m compileall test2
    
  • Дерево проекта после компиляции:

    test2
    ├── main.py
    ├── main.pyc
    └── subfolder
        ├── __init__.py
        ├── __init__.pyc
        ├── sub.py
        └── sub.pyc
    
  • Как видите, несколько .pyc генерируется вручную. Теперь я могу запустить этот проект, используя main.pyc как хорошо, что имеет отношение к sub.py:

    python main.pyc
    

    Из:

    Hi
    Bye
    
  • содержание main.py:

    from subfolder import sub
    
    print('Bye')
    
  • содержание sub.py:

    print('Hi')
    

Теперь я хочу повторить это поведение в проекте Python3.

Вот упрощенный asyncio (доступно в Python3) проект:

  • Дерево проекта:

    test3
    ├── main.py
    └── subfolder
        ├── __init__.py
        └── sub.py
    
  • Обобщение:

    python3 -m compileall test3
    
  • Дерево проекта после компиляции:

    test3
    ├── main.py
    ├── __pycache__
    │   └── main.cpython-36.pyc
    └── subfolder
        ├── __init__.py
        ├── __pycache__
        │   ├── __init__.cpython-36.pyc
        │   └── sub.cpython-36.pyc
        └── sub.py
    
  • Как вы видете, __pycache__ папки, созданные вручную. Но я не могу запустить этот проект, используя main.cpython-36.pyc который имеет отношение к subfolder:

    cd test3/__pycache__
    python3 main.cpython-36.pyc
    

    Out (я ожидал, что произвел Hi Bye сообщение):

    Traceback (most recent call last):
      File "test3/main.py", line 2, in <module>
    ModuleNotFoundError: No module named 'subfolder'
    
  • содержание main.py:

    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:

    print('Hi')
    

Вопрос:

Как я могу запустить этот проект (над проектом Python3), используя __pycache__ папка?

Или же

Как я могу запустить проект Python3 с отношением между подпапками, используя компиляцию Python?


[ПРИМЕЧАНИЕ]:

  • Я не могу использовать python compileall (Компиляция Python2) в выше Python3 проект из-за asyncio метод.

  • Моя версия Python(s) Python2.7 и Python3.6

1 ответ

Решение

Вы можете использовать тот же макет pyc-файлов в папках, что и в Python2, используя:

python3 -m compileall -b test3

Опция -b запускает вывод pyc -файлы в их унаследованные местоположения (т.е. такие же, как в Python2).

После этого вы можете снова использовать скомпилированный кеш через:

python3 main.pyc

Как работает загрузка модулей начиная с PEP-3147, невозможно использовать pyc-файлы из __pycache__ папка так, как вы собираетесь: если нет *.py -файл, содержание __pycache__ никогда не ищется. Вот самая важная часть рабочего процесса:

   import foo
     |
     |
     -- >  [foo.py exists?]  --- NO ----> [foo.pyc exists?]  -- NO --> [ImportError] 
            |                                     |
            |                                    YES
           YES                                    |--> [load foo.pyc]
            |
            |-> [look up in __pycache__]

Это означает, что файлы из __pycache__ только смотрят вверх, когда соответствующий *.py -файл можно найти.

Другие вопросы по тегам