2012-01-14 9 views
14

का उपयोग कर कोको एप्लिकेशन से पाइथन लिपि चला रहा है मैं कोको ऐप से पाइथन लिपि चलाने की कोशिश कर रहा हूं। यह मुख्य धागे पर ठीक काम कर रहा है, लेकिन मैं समवर्ती जीसीडी कतार पर पृष्ठभूमि में इसे चलाना चाहता हूं।जीसीडी

मैं सेटअप करने के लिए है कि अजगर स्क्रिप्ट चलाने से एक प्रबंधक वर्ग के लिए निम्न विधि का उपयोग कर रहा:

- (BOOL)setupPythonEnvironment { 
    if (Py_IsInitialized()) return YES; 

    Py_SetProgramName("/usr/bin/python"); 
    Py_Initialize(); 

    NSString *scriptPath = [[NSBundle mainBundle] pathForResource:@"MyScript"  ofType:@"py"]; 

    FILE *mainFile = fopen([scriptPath UTF8String], "r"); 
    return (PyRun_SimpleFile(mainFile, (char *)[[scriptPath lastPathComponent] UTF8String]) == 0); 
} 

स्क्रिप्ट है जो बाद (बार-बार) निम्नलिखित उदाहरण विधि से कहा जाता है, का एक साझा सिंगलटन उदाहरण का उपयोग करते हुए प्रबंधक वर्ग:

from Foundation import * 

def run_with_arguments(arguments): 
# ...a long-running script 

class MyScriptExecutor(NSObject): 
    @classmethod 
    def runWithArguments_(self, arguments): 
     return run_with_arguments(arguments) 
:

- (id)runScriptWithArguments:(NSArray *)arguments { 
    return [NSClassFromString(@"MyScriptExecutor") runWithArguments:arguments]; 
} 

ऊपर ऑब्जेक्टिव-सी कोड निम्नलिखित पायथन कोड में हुक

यह तब काम करता है जब मैं मुख्य कतार से उपर्युक्त उद्देश्य-सी विधियों को चलाता हूं, लेकिन किसी अन्य कतार से चलने पर स्क्रिप्ट शून्य हो जाती है। क्या कोई मुझे समझा सकता है कि मैं जो करने की कोशिश कर रहा हूं वह सिर्फ समर्थित नहीं है, और इसके आसपास कोई अच्छा तरीका है या नहीं?

पायथन स्क्रिप्ट को अक्सर कहा जाता है और लंबे समय तक चलता है, इसलिए मुख्य धागे पर ऐसा करना बहुत धीमा होगा, यह एक धारावाहिक कतार बन जाएगा। इसके अलावा, मैं जितना संभव हो सके उद्देश्य-सी के भीतर समवर्ती कोड शामिल करना चाहता हूं।

धन्यवाद,

+0

वास्तव में यह जानने के लिए पर्याप्त जानकारी नहीं है कि आप क्या कर रहे हैं। – jkh

+1

क्या आप मुझे बताएंगे कि आपने पाइथन बाइनरी को xcode के साथ कैसे एकीकृत किया? – bijan

उत्तर

11

this page से, ऐसा लगता है कि वहाँ कुछ कुछ बहुत जटिल सूत्रण अजगर को एम्बेड करने के लिए विशिष्ट चिंताएं हैं। क्या कोई कारण है कि आप इन स्क्रिप्ट को एक अलग प्रक्रिया में नहीं चला सकते? उदाहरण के लिए, निम्नलिखित -runBunchOfScripts विधि समानांतर पृष्ठभूमि कतार पर स्क्रिप्ट दस बार (-runPythonScript पर कॉल करके) परिणामस्वरूप आउटपुट को तारों की एक सरणी में एकत्रित करके, और फिर सभी स्क्रिप्ट पूर्ण होने के बाद आपकी ऑब्जेक्ट को मुख्य थ्रेड पर वापस कॉल करेगी यह सीमाओं, प्रक्रियाओं आप शुरू कर सकते हैं की संख्या पर हार्ड सीमा जा रहा है, लेकिन यह एक बहुत पूरे एम्बेड करने की तुलना में कम जोखिम से भरा लगता है, जिनमें से कम से कम नहीं है

- (NSString*)runPythonScript 
{ 
    NSTask* task = [[[NSTask alloc] init] autorelease]; 
    task.launchPath = @"/usr/bin/python"; 
    NSString *scriptPath = [[NSBundle mainBundle] pathForResource:@"MyScript" ofType:@"py"]; 
    task.arguments = [NSArray arrayWithObjects: scriptPath, nil]; 

    // NSLog breaks if we don't do this... 
    [task setStandardInput: [NSPipe pipe]]; 

    NSPipe *stdOutPipe = nil; 
    stdOutPipe = [NSPipe pipe]; 
    [task setStandardOutput:stdOutPipe]; 

    NSPipe* stdErrPipe = nil; 
    stdErrPipe = [NSPipe pipe]; 
    [task setStandardError: stdErrPipe]; 

    [task launch];   

    NSData* data = [[stdOutPipe fileHandleForReading] readDataToEndOfFile]; 

    [task waitUntilExit]; 

    NSInteger exitCode = task.terminationStatus; 

    if (exitCode != 0) 
    { 
     NSLog(@"Error!"); 
     return nil; 
    } 

    return [[[NSString alloc] initWithBytes: data.bytes length:data.length encoding: NSUTF8StringEncoding] autorelease]; 
} 

- (void)runBunchOfScripts 
{ 
    dispatch_group_t group = dispatch_group_create(); 
    NSMutableArray* results = [[NSMutableArray alloc] init]; 
    for (NSUInteger i = 0; i < 10; i++) 
    { 
     dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      NSString* result = [self runPythonScript]; 
      @synchronized(results) 
      { 
       [results addObject: result]; 
      } 
     }); 
    } 

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 
     [self scriptsDidFinishWithResults: results]; 
     dispatch_release(group); 
     [results release]; 
    }); 
} 

- (void)scriptsDidFinishWithResults: (NSArray*)results 
{ 
    NSLog(@"Do something with the results..."); 
} 

स्वाभाविक रूप से अलग प्रक्रियाओं का उपयोग करने का दृष्टिकोण है: दुभाषिया। मैं कहूंगा कि जब तक आपको स्क्रिप्ट और होस्टिंग पर्यावरण के बीच चैट करने की ज़रूरत नहीं है, यह एक बेहतर दृष्टिकोण होगा।

+0

धन्यवाद, @ipmcc। दुर्भाग्य से, स्क्रिप्ट को कई बार चलाना होगा। इतनी जल्दी ही उस कठिन सीमा को मारने के लिए पर्याप्त है। यही कारण है कि मैंने एक बार पाइथन पर्यावरण स्थापित करने की उम्मीद की थी, प्रत्येक स्क्रिप्ट चलाने के लिए केवल न्यूनतम ओवरहेड छोड़कर। वास्तव में, स्क्रिप्ट को पाइथन निष्पादक को एनएसएसटींग के रूप में भेजा जाता है, जिसे 'eval' के "सुरक्षित" संस्करण का उपयोग करके मूल्यांकन किया जाता है। –

+3

आप एनएसटीस्क के साथ एक समान समाधान कर सकते हैं; एक (या एन) लंबे समय से चल रहे पायथन दुभाषिया कार्य शुरू करें और इसे stdin से स्क्रिप्ट पढ़ें और उन्हें 'eval' करें, और फिर आप मानक आउटपुट से आउटपुट एकत्र कर सकते हैं। यदि आप केवल स्ट्रिंग का उपयोग करके अपनी स्क्रिप्ट्स से बातचीत कर सकते हैं, तो यह अभी भी दुभाषिया को एम्बेड करने से अधिक समझ में आता है (कम से कम जहां से मैं बैठा हूं।) – ipmcc

+0

शानदार। यह निश्चित रूप से यह करना चाहिए! –