2009-08-11 10 views
10

मैं जावा में एक ढांचा तैयार कर रहा हूं जो घटनाओं को सुनेंगे और फिर उन्हें ज्योथन में संसाधित करेगा। अलग-अलग ईवेंट प्रकार अलग-अलग स्क्रिप्ट पर भेजे जाएंगे।कैसे जावा से चल रहे मल्टीथ्रेडेड ज्योथन स्क्रिप्ट्स?

चूंकि PythonInterpreter.exec() को कॉल करते समय ज्योथन को स्क्रिप्ट संकलित करने में काफी समय लगता है, इसलिए मुझे स्क्रिप्ट को पूर्व-संकलित करना होगा। मैं इसे नीचे दिए तरीक़े कर रहा हूँ:

// initialize the script as string (would load it from file in final version) 
String script = "print 'foo'"; 
// get the compiled code object 
PyCode compiled = org.python.core.__builtin__.compile(script, "<>", "exec"); 

PyCode संकलित वस्तु के रूप में की घटनाओं

PythonInterpreter pi = new PythonInterpreter(); 
pi.set("variable_1", "value_1"); 
pi.set("variable_x", "value_x"); 
pi.exec(compiled); 

में आते हैं अब मेरी पहेली के लिए भंडार करने के लिए धक्का दिया और इस्तेमाल किया जाएगा - यह हो सकता है कई देखते हैं कि एक ही समय में कुछ प्रकार की घटनाएं हो रही हैं - इस प्रकार एक ही समय में स्क्रिप्ट के कई उदाहरण चल रहे हैं।

लगभग सभी लिपियों शायद अल्पकालिक रहेगा - 100 लाइनों, कोई छोरों पर निर्भर है। संख्या और आवृत्ति पूरी तरह से यादृच्छिक (उपयोगकर्ता उत्पन्न घटनाएं) है और प्रति ईवेंट प्रकार 0 से 200 प्रति सेकेंड तक हो सकती है।

ऐसा करने का सबसे अच्छा तरीका क्या होगा? मैं कुछ संभावनाएं पर देख रहा हूँ: ट्रिगर घटना बिंदु पर

  1. उपयोग तुल्यकालन - यह एक ही स्क्रिप्ट के कई उदाहरण रोका जा सके, लेकिन यह भी घटनाओं के रूप में जल्दी से संसाधित नहीं किया जाएगा के रूप में वे किया जाना चाहिए
  2. एक पूल बनाने एक ही प्रकार स्क्रिप्ट किसी भी तरह मूल PyCode वस्तु क्लोनिंग की आबादी की - इस तरह से अंतराल निकाल दिया जाता है - सबसे बड़ी समस्या शायद पूल आकार
  3. गतिशील जब भी जरूरत माता पिता से स्क्रिप्ट वस्तु क्लोन और फिर इसे त्यागने जब कार्यकारी() खत्म के अनुकूलन किया जाएगा संकलन से लेकिन यह अभी भी क्लोन विधि
में मौजूद है

शायद संख्या 2 और 3 का संयोजन सबसे अच्छा - गतिशील पूल आकार बनाना होगा?

तो, कोई विचार? ;)

उत्तर

3

यह एक दयालुता है कि PyCode उदाहरण अपरिवर्तनीय नहीं हैं (कक्षाओं में बहुत से सार्वजनिक सदस्य हैं)।

आप इस कोड का उपयोग एक पुन: प्रयोज्य स्क्रिप्ट precompile कर सकते हैं:

// TODO: generate this name 
final String name = "X"; 
byte[] scriptBytes = PyString.to_bytes(script); 
CompilerFlags flags = Py.getCompilerFlags(); 
ByteArrayOutputStream ostream = new ByteArrayOutputStream(); 
Module.compile(parser.parse(new ByteArrayInputStream(scriptBytes), "exec", 
    "<>", flags), ostream, name, "<>", false, false, false, flags); 
byte[] buffer = ostream.toByteArray(); 
Class<PyRunnable> clazz = BytecodeLoader.makeClass(name, null, buffer); 
final Constructor<PyRunnable> constructor = clazz 
    .getConstructor(new Class[] { String.class }); 

तो आप निर्माता का उपयोग स्क्रिप्ट के लिए PyCode उदाहरणों का उत्पादन कर सकते हैं जब भी आप एक की जरूरत है:

PyRunnable r = constructor.newInstance(name); 
PyCode pc = r.getMain(); 

मैं होगा सबसे पहले यह स्वीकार करने के लिए कि यह चीजों को करने का एक अच्छा तरीका नहीं है और शायद ज्योथन के साथ मेरे अनुभवहीनता के बारे में वॉल्यूम बोलता है। हालांकि, यह हर बार संकलन से काफी तेज है। कोड ज्योथन 2.2.1 के तहत काम करता है, लेकिन ज्योथन 2.5 (न ही आपका होगा) के तहत संकलित नहीं होगा।

+0

अच्छा! एक आकर्षण की तरह काम करता है;) यह ध्यान दिया जाना चाहिए कि पहले Module.compile (...) से पहले PythonInterpreter का एक उदाहरण बनाया जाना चाहिए। यदि SyspathJavaLoader से NullPointerException नहीं फेंक दिया गया है।loadClass() आप सबसे अधिक उपयोगी रहे हैं। अब मुझे बस इतना करना है कि स्क्रिप्ट के गतिशील रूप से पुनः आकार देने योग्य पूल में इसे एकीकृत करें ... – nEJC

+0

क्या आप ज्योथन 2.5 के लिए समकक्ष जानते हैं? – Laurent

+0

@Laurent - नहीं, मैंने इस क्षेत्र को नहीं देखा है क्योंकि मैंने यह उत्तर – McDowell

1

PythonInterpreter महंगा है, इस कोड को केवल एक का उपयोग करेगा।

#action.py 
def execute(filename, action_locals): 
    #add caching of compiled scripts here 
    exec(compile(open(filename).read(), filename, 'exec'), action_locals) 

//class variable, only one interpreter 
PythonInterpreter pi; 

//run once in init() or constructor 
pi = new PythonInterpreter();//could do more initialization here 
pi.exec("import action"); 

//every script execution 
PyObject pyActionRunner = pi.eval("action.execute"); 
PyString pyActionName = new PyString(script_path); 
PyDictionary pyActionLocals = new PyDictionary(); 
pyActionLocals.put("variable_1", "value_1"); 
pyActionLocals.put("variable_x", "value_x") 
pyActionRunner.__call__(pyActionName, pyActionLocals); 

#example_script.py 
print variable_1, variable_x 
+0

दिलचस्प पोस्ट किया है, लेकिन जहां तक ​​मुझे पता है कि PythonInterpreter थ्रेड-सुरक्षित नहीं है, इसलिए शायद यह एक अच्छा विचार नहीं है (कम से कम मेरे लिए) .. को कुछ परीक्षण करना होगा हालांकि ... – nEJC

+0

हां, पायथन इंटरप्रेटर थ्रेड-सुरक्षित नहीं है, यही कारण है कि मैंने इसे इस तरह से किया है। pi.eval ("action.execute") केवल आपको जावा वस्तु के रूप में विधि का एक उदाहरण देता है, इसे चलाता नहीं है। – Ron

संबंधित मुद्दे