2012-02-07 24 views
5

Küçük bir c sunucusu uygulaması geliştiriyoruz. Sunucu uygulaması bazı veri işlemlerini gerçekleştirir ve istemciye geri döner. Veri işlem parçasını yapılandırılabilir ve esnek tutmak için, Python'a gitmeye karar verdiğimiz çeşitli hazır modüllerin kullanılabilirliğine dayanarak komut dosyası kullanmaya karar verdik. C ve python arasındaki verileri göndermek/almak için Python-C API'sini kullanıyoruz.Python-C api eş zamanlılık sorunu

Algoritma şöyle çalışır: -

  1. Sunucu istemciden bazı verileri alır, bu veriler c oluşturulmuş bir sözlükte depolanır. Sözlük PyDict_New() işlevi kullanılarak oluşturulur; c. Giriş, api işlevi PyDict_SetItemString() kullanılarak sözlükte bir anahtar değer çifti olarak saklanır.
  2. Sonraki, python komut dosyasını PyRun_SimpleString(); komut dosyasını parametre olarak geçirme. Bu betik c'de oluşturulan sözlüğü kullanır. Unutmayın ki, c dilinde yaratılan sözlüğü, PyImport_AddModule() yöntemlerini kullanarak komut dosyasına erişilebildiğimizi lütfen unutmayın; ve PyModule_AddObject();
  3. Veri işlemenin sonucunu, komut dosyasında, yukarıda oluşturulan aynı sözlükte anahtar değer çifti olarak saklarız. C kodu daha sonra, betik yürütüldükten sonra sonuç değişkenine (anahtar/değer çifti) erişebilir.

Karşı karşıya olduğumuz sorun farklı müşteriler gelen eşzamanlı istek halinde olan sorun . Farklı istemcilerden birden çok istek geldiğinde, referans sayısı istisnalarını itiraz etme eğilimindeyiz. Bir kullanıcı için gelen her istek için, yalnızca o kullanıcı için bağımsız bir sözlük oluşturduğumuzu lütfen unutmayın. Bu sorunun üstesinden gelmek için PyRun_SimpleString(); PyEval_AcquireLock() içinde; ve PyEval_ReleaseLock(); ancak bunu yapmak, kod yürütmesinin engelleme çağrısı olmasını sağladı. Yani bir komut dosyası yürütmek için uzun zaman alıyorsa, diğer tüm kullanıcılar da bir yanıt beklemektedir.

Mümkün olan en iyi yaklaşımı önerebilir veya yanlış gittiğimiz noktalara işaretçiler verebilir misiniz? Lütfen daha fazla bilgi için bana ping.

Herhangi bir yardım/kılavuz takdir edilecektir.

cevap

1

Belki de, this answer numaralı belgede bahsedilen çağrılardan birini kaçırıyorsunuzdur.

+0

Referans için teşekkürler Jane. Bu arada, bu fonksiyonlara çağrı yapmıştım, ama hala işe yaramayacak. – Will

1

Muhtemelen http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock okumalısınız. Sorununuz ilk paragrafta açıklanmıştır.

GIL'i aldığınızda, Python nesnelerini doğrudan yönlendirdiğinizde yapın. PyRun_SimpleString'e yapılan çağrı GIL'i dahili olarak ele alacaktır ve uzun süreli operasyonlarda veya her X talimatında bunu verecektir. Bununla birlikte, gerçekten çok iş parçacıklı OLMAYACAKTIR.

Düzenleme:

Sen kilidi almak gerekir ve Python farklı bir iş parçacığı durumda olduğunun farkında olmasını sağlamak gerekir:

// acquire the lock and switch thread state 
PyEval_AcquireLock(); 
PyThreadState_Swap(perThreadState); 

// execute some python code 
PyEval_SimpleString("print 123"); 

// clear the thread state and release the lock 
PyThreadState_Swap(NULL); 
PyEval_ReleaseLock(); 
+0

Merhaba Tom, cevabınız için teşekkürler. Gerçekten çok iş parçacıklı "OLMAYACAĞIZ" gerçeğini ayrıntılı olarak açıklar mısınız?Senaryoların asla paralel olarak idam edilemeyeceğini mi söylüyorsun? – Will

+0

Genel bir yorumlayıcı kilidi vardır - kaç tane iş parçacığı olursa olsun, bir kerede yalnızca bir python bytecode komutu yürütülür. Dosya açma gibi uzun süren işlevler, yürütme sırasında geçici olarak kilidi serbest bırakır ve python yorumlayıcısı periyodik olarak kilidi verir, ancak sonuçta bir süreç içinde python bayt kodları seri olarak yürütülür. –

+0

Bu Tom için teşekkürler. Yanıtlarınız için zaman ayırın. Lütfen bunu doğrulayın: PyRun_SimpleString 2 (veya belki n) ayrı "c" iş parçacığında yürütürse, GIL'in kendisi ile ilgilenir ve dolayısıyla herhangi bir iş parçacığından PyRun_SimpleString'e çağrı yapmadan önce engellemem veya kilitlemem gerekmez. – Will

1

Sana multiprocessing modülünü araştırmak öneririm.

İlgili konular