У меня есть структура папок, как это:

  • script.py
  • folder_1
      < Литий> script.py < li> Сценарии < UL> < Литий> features.py < Литий> __init__.py
  • folder_2
      < Литий> script.py < li> Сценарии < UL> < Литий> features.py < Литий> __init__.py
  • В файле script.py верхнего уровня есть следующий код, который позволяет мне последовательно запускать каждый скрипт:

    import os
    
    list_filepath = ['folder_1','folder_2']
    
    for filepath in list_filepath:
        # change wd
        os.chdir(filepath)
        # run script.py
        exec(open('script.py').read())
    

    В файле script.py в folder_1 у меня есть следующий код:

    import os
    
    os.chdir('folder_1')
    
    import scripts.features as feat
    

    Сценарий features.py в папке folder_1 / scripts может содержать что-то вроде этого:

    LIST_FEATURES = ['feat_1','feat_2','feat_3']
    

    Запуск этого скрипта проходит без сбоев.

    В файле script.py в folder_2 у меня есть следующий код:

    import os
    
    os.chdir('folder_2')
    
    import scripts.features as feat
    

    Файл features.py в folder_2/scripts может содержать что-то вроде этого:

    LIST_OTHER_FEATURES = ['feat_4','feat_5','feat_6']
    

    Однако, когда я пытаюсь использовать функцию в этом модуле, я получаю:

    AttributeError: module 'scripts.features' has no attribute 'LIST_OTHER_FEATURES'
    

    Когда я запускаю feat сам по себе (в Spyder), он дает мне это:

    In[2]: feat
    Out[2]: <module 'scripts.features' from 'folder_1\\scripts\\features.py'>
    

    Так что, похоже, я пытаюсь использовать модуль features.py из folder_1, когда я хочу, чтобы он использовал модуль features.py из folder_2.

    Как я могу заставить это сделать это?

    0
    Aaron England 20 Апр 2020 в 20:13

    2 ответа

    Вы взламываете import, поэтому, когда вы chdir в folder1 и импортируете scripts, он импортирует его как scripts, а не folder1.scripts , Поэтому, когда вы переходите к folder2 и пытаетесь import scripts, фактически, похоже, что вы повторно импортируете то же самое. Так что этот модуль технически кешируется, и он просто использует folder1.scripts, который просто scripts. Для переводчика вы делаете это:

    import scripts.features
    import scripts.features
    

    Проиллюстрировать:

    import os
    os.chdir('folder_1/features')
    
    import features as f1
    
    dir(f1)
    ['F1_FEATURES', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
    
    os.chdir('../../folder_2/features')
    
    import features as f2
    
    dir(f2)
    # note, f2 is already seen as cached using the name f1
    ['F1_FEATURES', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
    

    Этот модуль уже кешируется. Итак, вам нужно реорганизовать структуру папок:

    • Главная папка /

        < Li> < р > script.py

        < Li> < p> folder_1 /

        < UL> < Литий> < р > __ __ INIT . Ру < Li> < p> особенности /

        < UL> < Li> __ __ INIT . Ру < Li> features.py
    < Li> < p> folder_2 /

    < UL> < Литий> < р > __ __ INIT . Ру < Li> < p> особенности /

    < UL> < Li> __ __ INIT . Ру < Li> features.py

    Который должен позволить вам использовать импорт вместо непосредственного выполнения файла для чтения (что вам не следует делать в любом случае)

    # in script.py
    from folder_1.features import features as f1
    from folder_2.features import features as f2
    
    # and checking out the things loaded in
    dir(f1)
    ['F1_FEATURES', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
    
    dir(f2)
    ['F2_FEATURES', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
    
    0
    C.Nivs 20 Апр 2020 в 17:53

    Когда вы import модуль / пакет Python ищет его в sys.modules, смотрите https://docs.python.org/3/reference/import.html#loading.

    Ты можешь:

    • создать spec из файла importlib.util.spec_from_file_location('foo', 'foo.py')
    • создать module с помощью importlib.util.module_from_spec(spec)
    • spec.loader.exec_module(module)

    Чтобы избежать именования коллизий.

    0
    KonstantinTogoi 20 Апр 2020 в 17:33