Встроенная функция reload () модифицированного модуля не работает, как я ожидал - PullRequest
0 голосов
/ 30 октября 2019

У меня есть некоторые функции, которые пишут код Python в файл. В моем тесте я создаю, импортирую, изменяю и перезагружаю модуль, но перезагрузка, кажется, не работает в python2.

test.py

from functions import create_config_file, append_config_list

def test_append_config_list():
    create_config_file()

    import config
    print('Before:')
    print(config.LIST)

    append_config_list(['item2', 'item3'])

    reload(config)
    print('After:')
    print(config.LIST)


if __name__ == '__main__':
    test_append_config_list()

functions.py

def create_config_file():
    text = """LIST = [
    'item1',
    'item2',
]
"""

    with open('config.py', 'w') as f:
        f.write(text)


def append_config_list(items):
    import config

    text = "LIST += [\n"
    for item in items:
        if item not in config.LIST:
            text += "    '{}',\n".format(item)
    text += "]\n"

    with open('config.py', 'a') as f:
        f.write(text)

Ожидаемое поведение

$ python2 test.py
Before:
['item1', 'item2']
After:
['item1', 'item2', 'item3']

Фактическое поведение

$ python2 test.py
Before:
['item1', 'item2']
After:
['item1', 'item2']

Если я использую python3 и заменяю встроенный reload() на importlib.reload(), все работает как положено.

Кто-нибудь знает, что я делаю здесь неправильно (кроме написания моей конфигурации в коде Python и ее импорта)?

1 Ответ

0 голосов
/ 30 октября 2019

Как я уже упоминал в комментарии, вам действительно не следует этого делать - формат данных, такой как JSON, YAML, TOML, или, если вам нужна дополнительная поддержка формата данных и нет читабельности человеком, лучше использовать Python pickle.

Кроме того, вы не должны запускать Python 2 - это EOL скоро.

В любом случае, запуск с python2 -v для отслеживания импорта привел меня к выяснению того, что происходит:

# ... snip ...
Python 2.7.17 (default, Oct 24 2019, 12:57:47)
# /Users/akx/Desktop/config.pyc has bad mtime
import config # from /Users/akx/Desktop/config.py
# wrote /Users/akx/Desktop/config.pyc
Before:
['item1', 'item2']
# /Users/akx/Desktop/config.pyc matches /Users/akx/Desktop/config.py
import config # precompiled from /Users/akx/Desktop/config.pyc
After:
['item1', 'item2']
# ... snip ...

Используется старый прекомпилированный config.pyc, даже если мы изменили config.py.

Добавление os.utime('config.py', None) в touch файла, чтобы сообщить Python, что он фактически обновлен, не имеетэффект здесь - вероятно, потому что времена файловой системы не имеют достаточного разрешения! Единственный обходной путь здесь - это посмотреть, есть ли у нас предварительно скомпилированный файл, и обработать его после редактирования файла .py:

with open('config.py', 'a') as f:
    f.write(text)
if os.path.isfile('config.pyc'):
    os.unlink('config.pyc')

... и вот:

Python 2.7.17 (default, Oct 24 2019, 12:57:47)
[GCC 4.2.1 Compatible Apple LLVM 11.0.0 (clang-1100.0.33.8)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
# /Users/akx/Desktop/config.pyc has bad mtime
import config # from /Users/akx/Desktop/config.py
# wrote /Users/akx/Desktop/config.pyc
Before:
['item1', 'item2']
LIST += [
    'item3',
]

import config # from /Users/akx/Desktop/config.py
# wrote /Users/akx/Desktop/config.pyc
After:
['item1', 'item2', 'item3']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...