2012-02-07 11 views
5

Opracowujemy małą aplikację serwera c. Aplikacja serwera przetwarza dane i odpowiada na klienta. Aby część przetwarzania danych była konfigurowalna i elastyczna, zdecydowaliśmy się na skrypty i na podstawie dostępności różnych gotowych modułów zdecydowaliśmy się na Python. Używamy api Python-C do wysyłania/odbierania danych pomiędzy c i python.Python-C api kwestia współbieżności

Algorytm działa tak: -

  1. Server odbiera niektóre dane od klienta, to dane są przechowywane w słowniku utworzonego wc. Słownik jest tworzony za pomocą funkcji api PyDict_New(); z c. Dane wejściowe są zapisywane jako para wartości klucza w słowniku za pomocą funkcji api PyDict_SetItemString();
  2. Następnie uruchamiamy skrypt Pythona PyRun_SimpleString(); przekazanie skryptu jako parametru. Ten skrypt korzysta ze słownika utworzonego w c. Zauważ, że tworzymy słownik utworzony w c, dostępny dla skryptu za pomocą metod PyImport_AddModule(); i PyModule_AddObject();
  3. Przechowujemy wynik przetwarzania danych w skrypcie jako parę wartości klucza w tym samym słowniku utworzonym powyżej. Kod c może po prostu uzyskać dostęp do zmiennej wyniku (pary klucz-wartość) po wykonaniu skryptu.

Problem Problem mamy do czynienia w przypadku jednoczesnych żądań pochodzących z różnych klientów. Gdy wiele żądań przychodzi od różnych klientów, mamy tendencję do unikania wyjątków liczników odwołań. Pamiętaj, że dla każdego żądania, które pochodzi od użytkownika, tworzymy niezależny słownik dla tego użytkownika. Aby rozwiązać ten problem, objęliśmy wywołanie PyRun_SimpleString(); w PyEval_AcquireLock(); i PyEval_ReleaseLock() ;, ale spowodowało to wykonanie skryptu będącego blokowaniem. Jeśli więc wykonanie skryptu trwa długo, wszyscy pozostali użytkownicy również czekają na odpowiedź.

Czy możesz zaproponować najlepsze możliwe podejście lub podać wskazówki, dokąd zmierzamy źle. Wyślij zapytanie do mnie, aby uzyskać więcej informacji.

Każda pomoc/wskazówki zostaną docenione.

Odpowiedz

1

Być może brakuje jednej z połączeń wymienionych w this answer.

+0

Dzięki za referencję Jane. Nawiasem mówiąc, nawiązywałem połączenia z tymi funkcjami, ale nadal nie będzie działać. – Will

1

Powinieneś prawdopodobnie przeczytać http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock Twój problem został wyjaśniony w pierwszym akapicie.

Kiedy zdobędziesz GIL, zrób to wokół bezpośredniej manipulacji obiektami w Pythonie. Wywołanie PyRun_SimpleString obsłuży GIL wewnętrznie i zrezygnuje z długotrwałych operacji lub po prostu co X instrukcji. NIE będzie jednak prawdziwie wielowątkowy.

Edit:

Musisz zdobyć zamek i trzeba upewnić się, że Python wie, że w innym stanie wątku:

// 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

Witaj Tomie, dzięki za odpowiedź. Czy mógłbyś rozwinąć fakt, że "NIE" będzie naprawdę wielowątkowy?Czy chcesz powiedzieć, że skrypty nie mogą zostać wykonane równolegle? – Will

+0

Istnieje globalna blokada interpretera - tylko jedna instrukcja bajtów pythonów będzie wykonywana w dowolnym momencie, bez względu na to, ile wątków jest. Długie funkcje, takie jak otwarcie pliku, zwalniają blokadę tymczasowo podczas wykonywania, a interpreter python okresowo rezygnuje z blokady, ale ostatecznie w ramach jednego procesu bajtowe bajty kodu są wykonywane szeregowo. –

+0

Dzięki za to Tom. Doceń czas na odpowiedzi. Potwierdź to: Jeśli PyRun_SimpleString jest wykonywany w 2 (lub może n) oddzielnych wątkach "c", to zajmuje się samym GIL, a więc nie muszę blokować ani blokować przed wykonaniem połączenia z PyRun_SimpleString z dowolnego wątku. – Will

1

Proponuję zbadać moduł multiprocessing.

Powiązane problemy