Найти - Пользователи
Полная версия: Как передать параметр в модуль в другом файле?
Начало » Python для новичков » Как передать параметр в модуль в другом файле?
1 2
xbow
Приложение с GUI (wx)
В приложении три (для упрощения) файла с кодом:
1. main.py - основной модуль
2. gui.py - модуль с классами GUI (wxGlade)
3. libdb.py - модуль с классами работы с MySQL
Изначально запускается main.py.
В нём создается объект интерфейса с БД и объект GUI
 dbconn = libdb.MysqlProvider(dbconn_params)
app = gui.MyApp(0)
app.MainLoop()
В процессе работы GUI предполагаются обращения к БД через объект dbconn. Но как передать этот объект внутрь объекта app, а точнее предоставить доступ к dbconn всем классам в модуле libdb.py?
Можно, конечно, так
 app = gui.MyApp(0, dbconn)
но это только в один класс, придётся тянуть с собой dbconn во всех вызовах остальных классов? Существует ли более удобный способ?


py.user.next
Составь список или словарь, а список или словарь потом передавай. Внутри класса общайся со словарём. Это конфигурация. Она должна быть строго определённой. А вот заполнять её можно произвольно.

Короче, суть. У тебя MyApp получает снаружи аргумент. Этот аргумент является объектом и имеет интерфейс для взаимодействия с ним. Что внутри этого объекта, классу MyApp неизвестно; класс MyApp знает только набор методов этого объекта для взятия тех или иных кусочков данных. Дальше ты сначала заполняешь этот объект до инстанциирования класса MyApp. Когда класс MyApp инстанциируется, ты в конструктор/инициализатор экземпляра класса MyApp подаёшь этот сформированный к этому моменту времени объект с конфигурацией внутри и методами снаружи. Экземпляр класса MyApp получает этот объект с конфигурацией внутри и дальше внутри себя общается с ним, получая из него идентификатор базы данных через метод.
xbow
примерно так?
main.py:
 import gui
import libdb
class ConfProv(object):
    def init(self):
        params = {}
    def put(self, key, value):
        params[key] = value
    def get(self, key):
        return params[key]
if __name__ == "__main__":
    conf = ConfProv()
    dbconn = libdb.MysqlProvider(dbconn_params)
    conf.put('dbconn', dbconn)
    app = gui.MyApp(0, conf)
    app.MainLoop()
ну и далее в gui.py:
 class MyApp(wx.App):
    def OnInit(self, conf):
        self.config = conf
        self.db = self.config.get('dbconn')
        ...
        self.db.makeQuery(strQuery)

но остается вопрос - как передавать этот self.config далее в вызываемые обработчиками событий панели/диалоги для выборки, например, списка пользователей, хранящимся в БД? Т.е. также передавать conf в вызове каждого подчиненного виджета wxPanel?
Было бы неплохо при инициализации класса MyApp этот параметр сохранить в глобальной для этого модуля переменной, чтобы можно было к ней обращаться из любого класса/виджета модуля. Но не уверен, что с классами это прокатит.
P.S. тут еще обнаружил: “метод OnInit() … не принимает никаких параметров…”, т.е. придется делать доп.метод для передачи conf в прикладной объект App
py.user.next
xbow
как передавать этот self.config далее в вызываемые обработчиками событий панели/диалоги для выборки
У каждого элемента должен быть свой конфигурационный объект, с которым он общается внутри себя, когда работает. Этот конфигурационный объект прикрепляется к нему при инстанциировании экземпляра этого элемента. У каждого элемента есть свой личный конфигурационный объект. Никакого общего конфигурационного объекта для всех не должно быть даже близко. Ты из этого общего конфигурационного объекта делаешь вот эти индвидуальные конфигурационные объекты на всех этапах в точках, в которых они требуются, а потом эти индивидуальные конфигурационные объекты передаёшь при инстанциировании этих элементов.

xbow
Было бы неплохо при инициализации класса MyApp этот параметр сохранить в глобальной для этого модуля переменной, чтобы можно было к ней обращаться из любого класса/виджета модуля.
Знаешь, ребёнок тоже думает, что неплохо было бы иметь вагон шоколода под окном и каждый день есть только шоколад из этого вагона, он ведь неплохо утоляет голод, поэтому почему бы и нет. Но родители не дадут ему это сделать и он даже будет на них обижаться хуй знает сколько времени за эти палки в колёсах его жизни. Но дело в том, что ребенок тупой, поэтому ты так не делай, как тебе там кажется, а делай так, как делают все успешные разработчики с эффективными программами, прочитавшие много книг и прошедшие по куче граблей.

Связи в программе надо разрывать, а не создавать. С чем это связано - вот пример тебе. У тебя есть печень внутри и есть чайник на кухне. Вот если у тебя чайник сгорел, то ты просто пошёл и купил новый, а через неделю уже забыл про старый чайник и не заметил вообще этой замены чайника. А вот если у тебя печень сломалась, то ты не можешь её заменить на другую. Она будет фурычить изо дня в день и таким образом сначала отравит кровь, а потом эта отравленная кровь отравит мозг и сердце. И главное, что ничего изменить нельзя. Если ты печень уберёшь, организм весь рухнет, потому что весь от неё зависит, а если ты её оставишь, организм весь отравится, потому что она сломалась. Вот чтобы такого не было в программе, все куски программы выносятся и делаются в виде таких чайников, а не в виде таких печеней. Когда программа эта вырастет, а она будет расти, то при любой поломке тебе надо будет заменить только маленький кусочек какой-то там где-то там в каком-то там месте, и это пройдёт незаметно для всей программы.


tags: modularity
xbow
py.user.next
У тебя есть печень внутри и есть чайник на кухне
Изоляция процессов, вещь, бесспорно, полезная, но иногда она мешает. ок. продолжим аналогию с организмом и чайником.
Вот есть необходимость снабдить все органы, в т.ч. и печень, водой из чайника. Исходя из твоего примера, я должен каждому органу приделать “рты”, через которые бы снабжал эти органы водой из чайника. А мне хочется иметь в классе “организм” только один “рот” и внутреннюю систему дистрибуции в подклассы “органы”. Т.е. ограничить число точек входа в отдельный модуль, обслуживающий своими классами определённый тип задач (gui, db, etc) - я не просто так приводил в примере разные фалы-модули.

Попытаюсь еще раз сформулировать задачу - каким образом организовать передачу параметра внутрь модуля (например, через главный класс) и распространение значения этого параметра среди других классов/подклассов этого модуля, не используя при этом передачу параметров при вызове/инициализации класса?
xbow
В общем решил задачу через global. Вот пример теста

main.py:
 # main.py
import db
import envr
global glvar
if __name__ == "__main__":
	cls = envr.Config("main value")
	cls.ShowParam("main")
	dbc = db.DbProv(cls)
	dbc.CheckConfig()
	dbc.CheckSub()

envr.py:
 # envr.py
class Config(object):
	def __init__(self, param):
		object.__init__(self)
		self.param = param      # тестовая переменная, получаемая при инициал. модуля
	def ShowParam(self, callmod):
		print("[%s] Config class param = %s" % (callmod, self.param))

db.py:
 # db.py
global glvar
# Подкласс модуля, получает ссылку на конфигурацию через глоб.переменную
class subDbProv(object):     
	def __init__(self):
		global glvar
		self.cfg = glvar     # иниц-ция лок. переменной ссылкой на глоб. переменную
        # проверка доступа к конфигурации через лок. переменную
	def CheckConfig(self):     
		self.cfg.ShowParam("subDbProv")
# Основной класс модуля, получает ссылку на конфигурацию через параметр вызова
class DbProv(object):
        # Инициализация класса, получение объекта конфигурации
	def __init__(self, cfg):  
		global glvar
		self.cfg = cfg
		glvar = cfg
        # Проверка доступа к конфигурации через лок. и глоб. переменные
	def CheckConfig(self):    
		global glvar
		self.cfg.ShowParam("db self")
		glvar.ShowParam("db glvar")
        # Проверка доступа к конфигурации в подклассе модуля через глоб. переменную
	def CheckSub(self):    
		obj = subDbProv()
		obj.CheckConfig()

Результат работы:
 [main] Config class param = main value
[db self] Config class param = main value
[db glvar] Config class param = main value
[subDbProv] Config class param = main value

py.user.next
xbow
продолжим аналогию с организмом и чайником.
Вот есть необходимость снабдить все органы, в т.ч. и печень, водой из чайника. Исходя из твоего примера, я должен каждому органу приделать “рты”, через которые бы снабжал эти органы водой из чайника.
Да, там бы никогда не вышло так, что кипяток полился бы в печень напрямую. Ведь чтобы чаю попить из чайника, нужно кипяток сделать в нём с помощью нагрева, а после чая этот кипяток в нём останется и дальше, не охладится внезапно. Но потом ты вдруг обнаруживаешь, что в чайнике-то кипяток, а печень, которая напрямую у тебя сосёт из чайника, на кипяток не расчитана. И вот тут-то у тебя и будет решение о том, чтобы повысить термостойкость печени. Ты же типа умный, а раз так, то надо думать над термостойкостью печени срочно.

Между печенью и чайником всегда можно вставить и термометр, и лёд. Но это между нормальными печенью и чайником, а не между твоими этими, прирощенными друг к другу ради удобства.

xbow
А мне хочется иметь в классе “организм” только один “рот” и внутреннюю систему дистрибуции в подклассы “органы”.
Ну, это распространённая ошибка, я же тебе не просто так это всё пишу. Ты куда-то в глупую сторону заворачиваешь - я тебе пишу “не ходи туда, это сломает программу”.

Но ты нихера не понимаешь, а когда ты не понимаешь чего-то, ты думаешь, что ты умный и все советчики дураки просто.

xbow
Т.е. ограничить число точек входа в отдельный модуль, обслуживающий своими классами определённый тип задач (gui, db, etc) - я не просто так приводил в примере разные фалы-модули.
Ну вот, когда несколько сотен наберётся, а не три штучки, тогда ты расскажешь, как ты здорово всё контролируешь в одном рте, в котором не три зуба к этому времени, а пятьсот тридцать восемь. К тому моменту ты уже не будешь помнить, какие модули у тебя есть в программе, а каких нет. И вот когда они все будут зависеть то от одного, то от другого и когда лишний раз нельзя будет пукнуть, чтобы не сломать всю программу сверху донизу, тогда я и посмотрю на тебя в тот момент, когда обнаружится какой-то баг и его надо будет срочно исправлять, потому что он критически всё портит и его нельзя оставлять точно ни на один день (программа работает где-то и делает важную вещь, за которую и посадить могут). Думаю, у тебя получится ситуация, как у компании Microsoft, когда периодически обновления системы просто ломают всё в системе. К этому уже давно все привыкли и это уже даже считается нормальным, что без этого невозможно существовать. Недавний случай, на этой неделе, сломал все браузеры. Там сначала слишком много индусов писали код тяп-ляп на отъебись называется, а потом вдруг баги поплыли проявляться у пользователей то тут то там, в том числе и спустя годы после тех индусов дешёвых. Так чтобы их исправить, понадобилось перерабатывать по полсистемы каждый раз, да и то это не закончилось успешно, так как отголоски этих исправлений до сих пор ломают всю систему при обновлениях.

Ты знаешь, почему язык Pascal умер, а язык C живёт? Потому что в Pascal встроили вывод в консоль, не предполагая даже, что когда-то консолей не станет в мире. А в языке C вывод в консоль - это просто библиотечная функция. Библиотеку всегда можно отключить, написать вместо неё другую библиотеку и подключить к языку новую библиотеку. Так с консолей можно перейти на сенсорные экраны, не затрагивая язык сам. А можно перейти и на нейронные интерфейсы году к 2050-му, пока что таких нет и мы о них даже думать не можем, потому что это придумают потом.

Мало ли что тебе там удобно, ты просто ребёнок, прыгающий вокруг вагона с шоколадом и пытающийся его весь сожрать за один день. Только дверца закрыта и ключик не подберёшь никак. Но взрослые рядом, не волнуйся, они дадут тебе по лбу и отправят делать уроки, скучные прескучные.
xbow
py.user.next
Мало ли что тебе там удобно, ты просто ребёнок, прыгающий вокруг вагона с шоколадом и пытающийся его весь сожрать за один день. Только дверца закрыта и ключик не подберёшь никак. Но взрослые рядом, не волнуйся, они дадут тебе по лбу и отправят делать уроки, скучные прискучные.
Был бы весьма благодарен тебе, если бы ты ручку “Снобизм” чуть-чуть прикрутил. А то 70% поста впустую занимают место на диске.
Писать “не туда поворачиваешь” без аргументации может любой. А вот конкретно пояснить - уже сложнее. Выше я привёл тестовую программу, на её примере можешь пояснить, в чем опасность такого применения глобальной переменной?
И чем этот пример не соответствует описанию в твоем первом ответе?
xam1816
xbow
в чем опасность такого применения глобальной переменной?
если какой-нибудь объект изменит значение глобальной переменной, что будет неожиданно для других объектов,которые ей тоже пользуются, то рухнет все что связано с этой глобальной переменной.Когда у тебя два объекта, ты еще поймешь что не так произошло,а если больше то будет тяжко
xbow
xam1816
если какой-нибудь объект изменит значение глобальной переменной, что будет неожиданно для других объектов, то рухнет все что связано с этой глобальной переменной.Когда у тебя два объекта, ты еще поймешь что не так произошло,а если больше то будет тяжко
Это понятно. Но и цель использования переменной - передать ссылку на объект конфигурации. Все вторичные классы не меняют эту переменную, а используют для доступа к существующему объекту.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB