2014-11-05 24 views
9

CherryPy ile COM üzerinden birkaç uygulamaya erişmesi gereken bir web uygulaması üzerinde çalışıyorum.Çoklu iş parçacığıyla win32com'u kullanma

Şu anda, her istekte uygulamanın yeni bir örneğini oluşturuyorum. Bu, her bir isteğin, uygulamanın başlaması için 3 saniye ve asıl iş için 0,01 saniye beklediği anlamına gelir.

Her COM uygulamasını bir kez başlatıp canlı tutmaya ve birkaç saniye boyunca aşağıdaki istekler doğrultusunda yeniden kullanmak istiyorum çünkü çoğu zaman 5-10 ajax isteğinin bir araya gelmesiyle kullanılır. .

Bir CherryPy uygulamasının tüm iş parçacıklarına bir COM eki paylaşması mümkün mü?

İşte her istekte nasıl çalıştığını ve iş parçacıkları boyunca nasıl çalışmadığını gösteren birkaç denemenin özeti.

Aşağıdaki kodu başarıyla başlar ve durur Excel:

>>> import pythoncom, win32com.client 
>>> def start(): 
    global xl 
    xl = win32com.client.Dispatch('Excel.Application') 

>>> def stop(): 
    global xl 
    xl.quit() 
    xl = None 

>>> start() 
>>> stop() 

Ama şu kod Excel başlatır ve 3 saniye sonra kapatır.

>>> import pythoncom, win32com.client, threading, time 
>>> def start(): 
    global xl 
    pythoncom.CoInitialize() 
    xl = win32com.client.Dispatch('Excel.Application') 
    time.sleep(3) 

>>> threading.Thread(target=start).start() 

başka türlü xl nesne ( this post bakınız) işe yaramaz CoInitialize() çağrısını ekledi.

Ve 3 saniyelik duraklamayı ekledim, bu nedenle EXCEL.EXE işleminin başladığını ve 3 saniye boyunca canlı olduğunu görev yöneticisi üzerinde görebiliyordum.

Başlatan iplik bittikten sonra neden öldürülür?

CoInitialize() belgelerini kontrol ettim, ancak çok iş parçacıklı ortamlarda çalışabilmenin mümkün olup olmadığını anlayamadım.

+1

hile (aka ücretsiz iş parçacıklı) iş parçacıklı daire için iplik kullanmak başlatılamıyor olabilir. [COInitializeEx] (http://docs.activestate.com/activepython/2.5/pywin32/pythoncom__CoInitializeEx_meth.html) 'COINIT_APARTMENTTHREADED' seçeneğiyle deneyin. Kod snippet'i için – tdelaney

cevap

7

Eğer birden çok iş parçacığında win32com kullanmak istiyorsanız, COMObject gibi bir iş parçacığına doğrudan iş parçacığından geçirilemezsiniz. Sen parçacıkları arasındaki örneğini geçmesine CoMarshalInterThreadInterfaceInStream() ve CoGetInterfaceAndReleaseStream() kullanmak gerekir:

import pythoncom, win32com.client, threading, time 

def start(): 
    # Initialize 
    pythoncom.CoInitialize() 

    # Get instance 
    xl = win32com.client.Dispatch('Excel.Application') 

    # Create id 
    xl_id = pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch, xl) 

    # Pass the id to the new thread 
    thread = threading.Thread(target=run_in_thread, kwargs={'xl_id': xl_id}) 
    thread.start() 

    # Wait for child to finish 
    thread.join() 

def run_in_thread(xl_id): 
    # Initialize 
    pythoncom.CoInitialize() 

    # Get instance from the id 
    xl = win32com.client.Dispatch(
      pythoncom.CoGetInterfaceAndReleaseStream(xl_id, pythoncom.IID_IDispatch) 
    ) 
    time.sleep(5) 


if __name__ == '__main__': 
    start() 

fazla bilgi için bkz: https://mail.python.org/pipermail/python-win32/2008-June/007788.html

+1

teşekkürler. oldukça kullanışlıdır. – Sanjit

İlgili konular