Уведомления

Группа в Telegram: @pythonsu

#1 Фев. 11, 2015 15:38:01

scurramalum
Зарегистрирован: 2014-07-22
Сообщения: 38
Репутация: +  1  -
Профиль   Отправить e-mail  

постоянное соединение

Добрый день
Ситуация такая: есть сайт (грубо говоря 1 страница) на джанго, к которой идет обращение из вне (с помощью ajax). В приложении на джанго при обращении выполняется некоторая функция, в которой идет подключение к COMConnector (1С). Дело в том, что сама функция выполняется достаточно быстро, и единственное, что ее сильно тормозит - инициализация подключения к КОМКоннектору.

Вопрос:
Есть ли возможность в джанго реализовать, чтобы Комконнектор инициализировался при запуске сервера, и после каким тогда образом к нему обращаться из view ?

Офлайн

#2 Фев. 11, 2015 17:17:07

GreyZmeem
От: Киев
Зарегистрирован: 2013-12-03
Сообщения: 147
Репутация: +  34  -
Профиль   Отправить e-mail  

постоянное соединение

Сделайте ваш коннектор class-member'ом

class ComConnectorMeta(type):
    connector = None
 
    def __new__(cls, *args, **kwargs):
        cls.connector = cls.init_connector()
        return super().__new__(cls, *args, **kwargs)
 
    @staticmethod
    def init_connector():
        """
        Ваш код инициализации коннектора
        """
        return 0
 
 
class ComConnector(metaclass=ComConnectorMeta):
    pass
После чего можете обращаться к нему ComConnector.connector. Тормоза будут только при первом обращении. Но учтите что ваш апплекейшен должен быть запущен в одном процессе, иначе если процессов несколько, то в каждом из них будет происходить инициализация.
Ну и разруливания race condition ложится на ваши плечи.

Если надо что-то делать при старте django, то для >=1.7 можно сделать так:
TestApp/__init__.py:
default_app_config = 'TestApp.apps.TestAppConfig'
TestApp/apps.py:
from django.apps import AppConfig
 
 
class TestAppConfig(AppConfig):
    name = 'TestApp'
    verbose_name = 'Test Application'
 
    def ready(self):
        """
        Your start up code goes here
        """
        pass
Только если вы запустите проект как ./manage.py run, то этот код выполнится два раза, т.к. django делает валидацию моделей и тд. В продакшене должно запускаться только один раз.

Офлайн

#3 Фев. 11, 2015 18:32:55

scurramalum
Зарегистрирован: 2014-07-22
Сообщения: 38
Репутация: +  1  -
Профиль   Отправить e-mail  

постоянное соединение

Спасибо, однако:

GreyZmeem
Но учтите что ваш апплекейшен должен быть запущен в одном процессе, иначе если процессов несколько, то в каждом из них будет происходить инициализация.

то есть если несколько человек будут обращаться к адресу, то коннектор все равно будет инициализироваться по новой? никак не сделать, чтобы соединение прошло 1 раз, и его могли использовать все пользователи? или я просто неправильно понял?

Офлайн

#4 Фев. 12, 2015 00:02:40

GreyZmeem
От: Киев
Зарегистрирован: 2013-12-03
Сообщения: 147
Репутация: +  34  -
Профиль   Отправить e-mail  

постоянное соединение

Нет. Я наверное неправильно выразился.

Например в uwsgi можно указать количество worker'ов и thread'ов.
worker'ы - количество процессов, которые будет запущено для обработки запросов.
thread - количество потоков в каждом процессе.
В пределах одного worker'а но разных thread'ов ваш ComConnector будет сохранят состояние.

Как пример, вам надо будет настроить uwsgi:

<workers>1</workers>
<enable-threads />
<threads>8</threads>

Возможно я что-то неправильно сказал и более опытные форумчане меня поправят

Офлайн

#5 Фев. 12, 2015 07:13:28

scurramalum
Зарегистрирован: 2014-07-22
Сообщения: 38
Репутация: +  1  -
Профиль   Отправить e-mail  

постоянное соединение

Большое спасибо, буду думать в этом направлении)

Офлайн

#6 Фев. 14, 2015 13:32:49

scurramalum
Зарегистрирован: 2014-07-22
Сообщения: 38
Репутация: +  1  -
Профиль   Отправить e-mail  

постоянное соединение

Никак не могу разобраться…питон 2.7, ругается на конструкцию

class ComConnector(metaclass=ComConnectorMeta):

В итоге немного подшаманил и привел ее к виду (скорее всего неправильно, но хотя бы так….):
class ComConnector(object):
    connector = None
    def __new__(cls, *args, **kwargs):
        if cls.connector is None:
            cls.connector = cls.init_connector()
        return cls.connector
 
    @staticmethod
    def init_connector():
        V81_CONN_STRING = "настройка подключения"
        V81 = win32com.client.Dispatch("V81.COMConnector").Connect(V81_CONN_STRING)
        return V81

и код во views.py:
def addorder2(request):
    V81 = ComConnector()
    pythoncom.CoInitialize()
    now = datetime.datetime.now(tzutc()) + datetime.timedelta(hours = 5)
    orderObject = getattr(V81.Documents, "Контакт").CreateDocument()
    setattr(orderObject, 'Дата', now)
    orderObject.Write(V81.DocumentWriteMode.Write)
    return HttpResponse(u'все сделано')

В итоге при первом обращении - все проходит успешно и документ записывается, а при втором - выдает ошибку:
AttributeError
views.py in addorder2
orderObject = getattr(V81.Documents, "Контакт").CreateDocument() 
C:\Python27\lib\site-packages\win32com\client\dynamic.py in __getattr__
raise AttributeError("%s.%s" % (self._username_, attr))

помогите пожалуйста это исправить….

Отредактировано scurramalum (Фев. 14, 2015 19:35:23)

Офлайн

#7 Фев. 15, 2015 08:38:01

scurramalum
Зарегистрирован: 2014-07-22
Сообщения: 38
Репутация: +  1  -
Профиль   Отправить e-mail  

постоянное соединение

Вот, получилось реализовать вариант который работает (в упрощенном виде):

#coding=cp1251
import win32com.client
import pythoncom
import datetime
from dateutil.tz import tzutc, tzlocal
class ComConnectorMeta(type):
    connector = None
 
    def __new__(cls, *args, **kwargs):
        cls.connector = cls.init_connector()
        return super().__new__(cls, *args, **kwargs)
 
    @staticmethod
    def init_connector():
        pythoncom.CoInitialize()
        V81_CONN_STRING = "Настройка подключения"
        CON = win32com.client.Dispatch("V81.COMConnector").Connect(V81_CONN_STRING)
        return CON
 
 
class ComConnector(metaclass=ComConnectorMeta):
    pass
def func():
    V81 = ComConnector.connector
    print(V81)
    now = datetime.datetime.now(tzutc()) + datetime.timedelta(hours = 5)
    orderObject = getattr(V81.Documents, "Контакт").CreateDocument()
    setattr(orderObject, 'Дата', now)
    orderObject.Write(V81.DocumentWriteMode.Write)
    print('запись успешна')
func()
func()

Проблема в том, что он работает на 3 python.

Помогите, пожалуйста, перевести вариант в python 2.7

Офлайн

#8 Фев. 15, 2015 09:37:06

scurramalum
Зарегистрирован: 2014-07-22
Сообщения: 38
Репутация: +  1  -
Профиль   Отправить e-mail  

постоянное соединение

Заставил работать на 2.7….но опять проблема:

#coding=cp1251
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseServerError
from django.db import connections
import win32com.client
import pythoncom
import datetime
from dateutil.tz import tzutc, tzlocal
import pywintypes
class ComConnectorMeta(type):
    connector = None
 
    def __new__(cls, *args, **kwargs):
        if cls.connector == None:
            cls.connector = cls.init_connector()
        return super(ComConnectorMeta, cls).__new__(cls, *args, **kwargs)
 
    @staticmethod
    def init_connector():
        pythoncom.CoInitialize()
        V81_CONN_STRING = "Настройка подключения"
        CON = win32com.client.Dispatch("V81.COMConnector").Connect(V81_CONN_STRING)
        return CON
 
 
class ComConnector():
    __metaclass__ = ComConnectorMeta
def addorder2(request):
    V81 = ComConnector.connector
    now = datetime.datetime.now(tzutc()) + datetime.timedelta(hours = 5)
    orderObject = getattr(V81.Documents, "Контакт").CreateDocument()
    setattr(orderObject, 'Дата', now)
    orderObject.Write(V81.DocumentWriteMode.Write)
    return HttpResponse(u'все хорошо')

При первом обращении к странице - проходит инициализация и успешная запись.
Но при повторном - появляется все та же ошибка:
AttributeError
Connect.Documents
orderObject = getattr(V81.Documents, “Контакт”).CreateDocument()
raise AttributeError(“%s.%s” % (self._username_, attr))


Странно, что если это сделать просто как скрипт в виде:
#coding=cp1251
import win32com.client
import pythoncom
import datetime
from dateutil.tz import tzutc, tzlocal
class ComConnectorMeta(type):
    connector = None
 
    def __new__(cls, *args, **kwargs):
        if cls.connector == None:
            cls.connector = cls.init_connector()
        return super(ComConnectorMeta, cls).__new__(cls, *args, **kwargs)
 
    @staticmethod
    def init_connector():
        pythoncom.CoInitialize()
        V81_CONN_STRING = "Srvr=1C;Ref=REG_COPY;Usr=adminchel;Pwd=123;"
        CON = win32com.client.Dispatch("V81.COMConnector").Connect(V81_CONN_STRING)
        return CON
 
 
class ComConnector():
    __metaclass__ = ComConnectorMeta
def addorder2():
    V81 = ComConnector.connector
    now = datetime.datetime.now(tzutc()) + datetime.timedelta(hours = 5)
    orderObject = getattr(V81.Documents, "Контакт").CreateDocument()
    setattr(orderObject, 'Дата', now)
    orderObject.Write(V81.DocumentWriteMode.Write)
    print(u'все хорошо')
if __name__ == '__main__':
    addorder2() #первый вызов функции
    addorder2() #второй вызов функции

Все работает отлично, и делается подряд 2 записи, время на инициализацию уходит только 1 раз…
Подскажите, в чем ошибка? Скорее всего я чего-то не понимаю…

Офлайн

#9 Фев. 15, 2015 12:38:38

scurramalum
Зарегистрирован: 2014-07-22
Сообщения: 38
Репутация: +  1  -
Профиль   Отправить e-mail  

постоянное соединение

Покопал еще чуть поглубже:
оказывается, при повторном обращении к функции во views.py, тип коннектора определяется правильно <COMobject Connect>, также сохраняется его id, что указывает что объект тот же самый, однако при попытке его вывести в консоль с помощью print - пишет что “Объект не подключен к серверу”…

Копаем дальше…

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version