Несколько сценариев обращаются к одному и тому же модулю с одинаковыми данными в python?

#python

#python

Вопрос:

Недавно я пытался создать самодельный считыватель «дискового пространства». Я создал библиотеку, которая хранит значения в списке «диск», и когда я выполняю подпроцесс нового скрипта для записи на «диск», чтобы увидеть, изменяются ли значения на дисплее, ничего не происходит. Я понял, что каждый раз, когда вы импортируете модуль, модуль как бы клонирует себя только к этому сценарию.

Я хочу, чтобы скрипты могли импортировать один и тот же модуль, и чтобы, если 1 скрипт изменяет значение, другой скрипт мог видеть это значение.

Вот мой код для «дисковой» системы

 import time
ram = []
space = 256000
lastspace = 0
for i in range(0,space   1):
    ram.append('')

def read(location):
    try:
        if ram[int(location)] == '':
            return "ERR_NO_VALUE"
        else:
            return ram[int(location)]
    except:
        return "ERR_OUT_OF_RANGE"

def write(location, value):
    try:
        ram[int(location)] = value
    except:
        return "ERR_OUT_OF_RANGE"

def getcontents():
    contents = []
    for i in range(0, 256001):
        contents.append([str(i)  '- ', ram[i]])
    return contents

def getrawcontents():
    contents = []
    for i in range(0, 256001):
        contents.append(ram[i])
    return contents

def erasechunk(beg, end):
    try:
        for i in range(int(beg), int(end)   1):
            ram[i] = ''
    except:
        return "ERR_OUT_OF_RANGE"

def erase(location):
    ram[int(location)] = ''

def reset():
    ram = []
    times = space/51200
    tc = 0
    for i in range(0,round(times)):
        for x in range(0,51201):
            ram.append('')
            tc  = 1
            print("Byte "   str(tc)   " of "   " Bytes")
        for a in range(0,100):
            print('a', end='')

    return [len(ram), ' bytes']

def wipe():
    for i in range(0,256001):
        ram[i] = ''
    return "WIPED"

def getspace():
    x = 0
    for i in range(0,len(ram)):
        if ram[i] != "":
            x  = 1
    return [x,256000]
 

Комментарии:

1. Проблема в том, как вы вызываете этот скрипт, а не в самом скрипте, пожалуйста, измените его, чтобы показать минимальный пример того, где вызов этих функций вызывает у вас проблему? т. е. Где вы «подпроцессируете новый скрипт для записи на «диск» `. Если у вас есть два полностью независимых файла .py, отдельно импортирующих приведенный выше код, они не смогут каким-либо образом взаимодействовать друг с другом.

Ответ №1:

Самый короткий ответ на ваш вопрос, который я понимаю как «если я import разделяю одну и ту же функцию на две (или более) Пространства имен Python, могут ли они взаимодействовать друг с другом?», нет. Что на самом деле происходит, когда вы import используете модуль, так это то, что Python использует исходный скрипт для «сборки» этих функций в пространстве имен, в которое вы их импортируете; нет никакого смысла постоянства в том, «откуда взялся модуль», поскольку этот исходный модуль фактически нигде не запускается в процессе Python! Когда вы используете import эти функции в нескольких сценариях, он просто создаст эти псевдоглобальные переменные (в вашем случае ram ) с импортируемой функцией.

import Документы Python: https://docs.python.org/3/reference/import.html

Вся страница модели данных Python, включая то, что __globals__ означает для функций и модулей: https://docs.python.org/3/reference/datamodel.html

Объяснение:

Чтобы углубиться, когда вы импортируете любую из функций из этого скрипта (предположим, он называется ‘disk.py ‘), вы получите объект в __globals__ вызываемом dict этой функции ram , который действительно будет работать так, как вы ожидаете для этих функций в вашем текущем пространстве имен:

 from disk import read,write
write(13,'thing')
print(read(13)) #prints 'thing'
 

Мы могли бы предположить, поскольку эти функции точно обращаются к нашему ram объекту, что ram объект каким-то образом модифицируется в пространстве имен исходного скрипта, к которому затем может быть доступен другой скрипт (другой процесс Python). Просмотр пространства имен нашего текущего скрипта, использующего dir() , может поддержать это понятие, поскольку мы видим только read and write , а не ram . Но секрет в том, что ram скрыто в __globals__ dict этих функций (упомянуто выше), то есть как функции взаимодействуют с ram :

 from disk import read,write
print(type(write.__globals__['ram'])) #<class 'list'>
print(write.__globals__['ram'] is read.__globals__['ram']) #True
write(13,'thing')
print(read(13)) #'thing'
print(read.__globals__['ram'][13]) #'thing'
 

Как вы можете видеть, ram actually — это переменная, определенная в пространстве имен нашего текущего процесса Python, скрытая в __globals__ dict функций, которая на самом деле является точно таким же словарем для любой функции, импортированной из того же модуля; read.__globals__ is write.__globals__ оценивается как True (даже если вы не импортируете их одновременно!).

Итак, чтобы завершить все это, ram содержится в __globals__ dict для disk модуля, который создается отдельно в пространстве имен каждого процесса, в который вы импортируете:

Интерпретатор Python # 1:

 from disk import read,write
print(id(read.__globals__),id(write.__globals__)) #139775502955080 139775502955080
 

Интерпретатор Python # 2:

 from disk import read,write
print(id(read.__globals__),id(write.__globals__)) #139797009773128 139797009773128
 

Подсказка по решению:

Существует много подходов к тому, как сделать это практически, которые выходят за рамки этого ответа, но я предположу, что pickle это стандартный способ отправки объектов между интерпретаторами Python с использованием файлов и имеет действительно стандартный интерфейс. Вы можете просто записывать, читать и т. Д. Свой ram объект, Используя файл pickle. Для записи:

 import pickle
with open('./my_ram_file.pkl','wb') as ram_f:
    pickle.dump(ram,ram_f)
 

Для чтения:

 import pickle
with open('./my_ram_file.pkl','rb') as ram_f:
    ram = pickle.load(ram_f)
 

Комментарии:

1. Хорошо, это имеет гораздо больше смысла. Я собираюсь попробовать.