Question

What is a method that forces python to run in 64 mode from a NSTask?

Update: As per Ned's suggestion I tried referencing Python2.7 directly with objective c and that worked. Changed @"/usr/bin/python" to @"/usr/bin/python2.7". The new code is at the bottom of the question.

I have a 64 bit system. When run from terminal python runs in 64 bit. When I run a plain shell from a NSTask running /usr/bin/uname -m it returns x86_64.

I've tried using arch but the shell running python is still in 32 bit mode.

Example method

-(void) runPython64BitScriptViaArchWithPath:(NSString*)path {

    NSTask* task = [[NSTask alloc] init];
    task.launchPath = @"/usr/bin/arch" ;
    task.arguments = [NSArray arrayWithObjects: @"-x86_64", @"/usr/bin/python", path, nil];

    [task setStandardInput:[NSPipe pipe]] ;

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

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

    NSLog(@"%@", [task arguments]) ;

    [task launch] ;

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

    [task waitUntilExit];

    NSInteger exitCode = task.terminationStatus;

    if (exitCode != 0)
    {
        NSLog(@"Error!");
        NSData *error = [[stdErrPipe fileHandleForReading] readDataToEndOfFile] ;
        NSLog(@"Exit code : %ld", (long)exitCode) ;
        NSString *result = [[NSString alloc] initWithBytes: error.bytes length:error.length encoding: NSUTF8StringEncoding] ;
        NSLog(@"%@",result);
        [result release];
    } else {
        NSString *result = [[NSString alloc] initWithBytes: data.bytes length:data.length encoding: NSUTF8StringEncoding] ;
        NSLog(@"%@",result) ;
        [result release];
    }
    [task release] ;

}

an example python script that works if run from terminal

#!/usr/bin/env python
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'social_shields.settings'

try:
    import hosts.models
    shield = hosts.models.Shield.objects.all()[0]
    shield.active = True
    shield.save()
except Exception as exception:
    import struct
    print 'Bits : %s' % ( 8 * struct.calcsize("P"))
    print exception

example log

2013-07-04 16:10:31.600 socialshield[88688:303] onShieldDown
2013-07-04 16:10:31.607 socialshield[88688:303] x86_64
2013-07-04 16:10:31.607 socialshield[88688:303] (
    "-x86_64",
    "/usr/bin/python",
    "/source/social_shields/social_shields/shield_down.py"
)
2013-07-04 16:10:31.933 socialshield[88688:303] Bits : 32
Error loading MySQLdb module: dlopen(/Library/Python/2.7/site-packages/_mysql.so, 2): no suitable image found.  Did find:
    /Library/Python/2.7/site-packages/_mysql.so: mach-o, but wrong architecture

new code that works after applying Ned's suggestion :-)

-(void) runPython64BitScriptViaArchWithPath:(NSString*)path {

    NSTask* task = [[NSTask alloc] init];
    task.launchPath = @"/usr/bin/arch" ;
    task.arguments = [NSArray arrayWithObjects: @"-x86_64", @"/usr/bin/python2.7", path, nil];

    [task setStandardInput:[NSPipe pipe]] ;

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

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

    NSLog(@"%@", [task arguments]) ;

    [task launch] ;

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

    [task waitUntilExit];

    NSInteger exitCode = task.terminationStatus;

    if (exitCode != 0)
    {
        NSLog(@"Error!");
        NSData *error = [[stdErrPipe fileHandleForReading] readDataToEndOfFile] ;
        NSLog(@"Exit code : %ld", (long)exitCode) ;
        NSString *result = [[NSString alloc] initWithBytes: error.bytes length:error.length encoding: NSUTF8StringEncoding] ;
        NSLog(@"%@",result);
        [result release];
    } else {
        NSString *result = [[NSString alloc] initWithBytes: data.bytes length:data.length encoding: NSUTF8StringEncoding] ;
        NSLog(@"%@",result) ;
        [result release];
    }
    [task release] ;

}
Was it helpful?

Solution

I assume you have verified that /Library/Python/2.7/site-packages/_mysql.so is 64-bit and that you are really using the same Python in both cases. On OS X 10.6 and later systems, /usr/bin/python is actually a wrapper executable that determines which version of Python and which architecture (32-bit or 64-bit) to run; see man 1 python for details. Try executing /usr/bin/python2.7 directly. That should default to 64-bit. You can also check whether Python is running in 32- or 64-bit mode by using this documented test:

import sys; print(sys.maxsize > 2**32)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top