Call Python code from an existing project written in Swift - python

I need a way to call Python code from Swift on an Apple platform. A library would be ideal. I've done a considerable amount of Google searching, and the closest material I found is for Objective-C.

In swift 5 you can try PythonKit framework.
Here's example of the usage:
import PythonKit
let sys = try Python.import("sys")
print("Python \(sys.version_info.major).\(sys.version_info.minor)")
print("Python Version: \(sys.version)")
print("Python Encoding: \(sys.getdefaultencoding().upper())")

I found this excellent and up to date gist that walks you through a complete solution: https://github.com/ndevenish/Site-ndevenish/blob/master/_posts/2017-04-11-using-python-with-swift-3.markdown
If you can get away with just using NSTask to launch a Python process, that's a pretty good option too.

In Swift 4.2 there was an approved feature to allow dynamic languages to be ported directly into swift
https://github.com/apple/swift-evolution/blob/master/proposals/0195-dynamic-member-lookup.md
Will look similar to:
// import pickle
let pickle = Python.import("pickle")
// file = open(filename)
let file = Python.open(filename)
// blob = file.read()
let blob = file.read()
// result = pickle.loads(blob)
let result = pickle.loads(blob)

If anyone is ever interested in calling python from swift, here is some helpful material I found:
U the python framework - https://developer.apple.com/library/ios/technotes/tn2328/_index.html
PyObjC (a little more challenging) -
Cobbal - https://github.com/cobbal/python-for-iphone
Python docs (you would need to make C-Swift bridge)
Most of it is for Objective-c, but if you need to use swift you can easily just create an ObjC-Swift bridge (super-super easy) - Lookup the apple docs

Related

Tensorrt Plugin and caffe parser in python

I am new to Tensorrt and I am not so familiar with C language also. May I ask if there is any example to import caffe modell(caffeparser) and at the same time to use plugin with python. Plugin library example: "https://docs.nvidia.com/deeplearning/sdk/tensorrt-api/c_api/_nv_infer_plugin_8h_source.html".
I saw an example doing something like the below. Is it necessary to modify the the pluginfactory class? or it has been already done with the python plugin api?
import tensorrt
import tensorrtplugins
from tensorrt.plugins import _nv_infer_plugin_bindings as nvinferplugin
from tensorrt.parsers import caffeparser
plugin_factory = tensorrtplugins.FullyConnectedPluginFactory()
parser = caffeparser.create_caffe_parser()
parser.set_plugin_factory(plugin_factory)
engine = trt.utils.caffe_to_trt_engine(G_LOGGER,
MODEL_PROTOTXT,
CAFFE_MODEL,
1,
1 << 20,
OUTPUT_LAYERS,
trt.infer.DataType.FLOAT,
plugin_factory
)
P.s: I am trying to convert YOLO2 to Tensorrt format. Therefore, some layers(e.g kYOLOREORG and kPRELU) can only be supported by the plugin.
Another way to do so is to add the plugin during constructing the network, by method network.add_plugin_ext() ?However, I am not so sure how to specify the previous layer that is going to be imported later.
Thank you so much for your answer. Your help will be much appreciated!

Python Scripting for Abaqus

I am new to Abaqus Python Scripting. The following line of code in my script is throwing a keyword error (Type Error: Keyword error on mergeWire).
myPart.WirePolyLine(points = myPoints, mergeWire = OFF, meshable = ON)
where
myPoints = ((datum_points[crossPart_datums_keys[0]],datum_points[crossPart_datums_keys[1]]),datum_points[crossPart_datums_keys[2]],datum_points[crossPart_datums_keys[3](datum_points[crossPart_datums_keys[4]],datum_points[crossPart_datums_keys[5]]),(datum_points[crossPart_datums_keys[6]],datum_points[crossPart_datums_keys[7]]),(datum_points[crossPart_datums_keys[8]],datum_points[crossPart_datums_keys[9]]),(datum_points[crossPart_datums_keys[10]],datum_points[crossPart_datums_keys[11]]),(datum_points[crossPart_datums_keys[12]],datum_points[crossPart_datums_keys[13]]),(datum_points[crossPart_datums_keys[14]],datum_points[crossPart_datums_keys[15]]))
Can someone help me to fix this?
Looking at Abaqus 6.14 Scripting Reference Guide, WirePolyLine has two arguments, points and mergeType. mergeWire and meshable are not listed as arguments. Perhaps you should use:
from abaqusConstants import SEPARATE
myPart.WirePolyLine(points = myPoints, mergeType = SEPARATE)
I strongly suggest you consult section 37.2.56 of Abaqus 6.14 Scripting Reference Guide.
dear friend, I am also a beginner in abacus, but I think the contents of this link can help you in this matter, the good thing is that it is free.
Caeassistant

How to use Win32 API with Python?

How can I use win32 API in Python?
What is the best and easiest way to do it?
Can you please provide some examples?
PyWin32 is the way to go - but how to use it? One approach is to begin with a concrete problem you're having and attempting to solve it. PyWin32 provides bindings for the Win32 API functions for which there are many, and you really have to pick a specific goal first.
In my Python 2.5 installation (ActiveState on Windows) the win32 package has a Demos folder packed with sample code of various parts of the library.
For example, here's CopyFileEx.py:
import win32file, win32api
import os
def ProgressRoutine(TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred,
StreamNumber, CallbackReason, SourceFile, DestinationFile, Data):
print Data
print TotalFileSize, TotalBytesTransferred, StreamSize, StreamBytesTransferred, StreamNumber, CallbackReason, SourceFile, DestinationFile
##if TotalBytesTransferred > 100000:
## return win32file.PROGRESS_STOP
return win32file.PROGRESS_CONTINUE
temp_dir=win32api.GetTempPath()
fsrc=win32api.GetTempFileName(temp_dir,'cfe')[0]
fdst=win32api.GetTempFileName(temp_dir,'cfe')[0]
print fsrc, fdst
f=open(fsrc,'w')
f.write('xxxxxxxxxxxxxxxx\n'*32768)
f.close()
## add a couple of extra data streams
f=open(fsrc+':stream_y','w')
f.write('yyyyyyyyyyyyyyyy\n'*32768)
f.close()
f=open(fsrc+':stream_z','w')
f.write('zzzzzzzzzzzzzzzz\n'*32768)
f.close()
operation_desc='Copying '+fsrc+' to '+fdst
win32file.CopyFileEx(fsrc, fdst, ProgressRoutine, operation_desc, False, win32file.COPY_FILE_RESTARTABLE)
It shows how to use the CopyFileEx function with a few others (such as GetTempPath and GetTempFileName). From this example you can get a "general feel" of how to work with this library.
PyWin32, as mentioned by #chaos, is probably the most popular choice; the alternative is ctypes which is part of Python's standard library. For example, print ctypes.windll.kernel32.GetModuleHandleA(None) will show the module-handle of the current module (EXE or DLL). A more extensive example of using ctypes to get at win32 APIs is here.
The important functions that you can to use in win32 Python are the message boxes, this is classical example of OK or Cancel.
result = win32api.MessageBox(None,"Do you want to open a file?", "title",1)
if result == 1:
print 'Ok'
elif result == 2:
print 'cancel'
The collection:
win32api.MessageBox(0,"msgbox", "title")
win32api.MessageBox(0,"ok cancel?", "title",1)
win32api.MessageBox(0,"abort retry ignore?", "title",2)
win32api.MessageBox(0,"yes no cancel?", "title",3)

calling Objective C functions from Python?

Is there a way to dynamically call an Objective C function from Python?
For example, On the mac I would like to call this Objective C function
[NSSpeechSynthesizer availableVoices]
without having to precompile any special Python wrapper module.
As others have mentioned, PyObjC is the way to go. But, for completeness' sake, here's how you can do it with ctypes, in case you need it to work on versions of OS X prior to 10.5 that do not have PyObjC installed:
import ctypes
import ctypes.util
# Need to do this to load the NSSpeechSynthesizer class, which is in AppKit.framework
appkit = ctypes.cdll.LoadLibrary(ctypes.util.find_library('AppKit'))
objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc'))
objc.objc_getClass.restype = ctypes.c_void_p
objc.sel_registerName.restype = ctypes.c_void_p
objc.objc_msgSend.restype = ctypes.c_void_p
objc.objc_msgSend.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
# Without this, it will still work, but it'll leak memory
NSAutoreleasePool = objc.objc_getClass('NSAutoreleasePool')
pool = objc.objc_msgSend(NSAutoreleasePool, objc.sel_registerName('alloc'))
pool = objc.objc_msgSend(pool, objc.sel_registerName('init'))
NSSpeechSynthesizer = objc.objc_getClass('NSSpeechSynthesizer')
availableVoices = objc.objc_msgSend(NSSpeechSynthesizer, objc.sel_registerName('availableVoices'))
count = objc.objc_msgSend(availableVoices, objc.sel_registerName('count'))
voiceNames = [
ctypes.string_at(
objc.objc_msgSend(
objc.objc_msgSend(availableVoices, objc.sel_registerName('objectAtIndex:'), i),
objc.sel_registerName('UTF8String')))
for i in range(count)]
print voiceNames
objc.objc_msgSend(pool, objc.sel_registerName('release'))
It ain't pretty, but it gets the job done. The final list of available names is stored in the voiceNames variable above.
2012-4-28 Update: Fixed to work in 64-bit Python builds by making sure all parameters and return types are passed as pointers instead of 32-bit integers.
Since OS X 10.5, OS X has shipped with the PyObjC bridge, a Python-Objective-C bridge. It uses the BridgeSupport framework to map Objective-C frameworks to Python. Unlike, MacRuby, PyObjC is a classical bridge--there is a proxy object on the python side for each ObjC object and visa versa. The bridge is pretty seamless, however, and its possible to write entire apps in PyObjC (Xcode has some basic PyObjC support, and you can download the app and file templates for Xcode from the PyObjC SVN at the above link). Many folks use it for utilities or for app-scripting/plugins. Apple's developer site also has an introduction to developing Cocoa applications with Python via PyObjC which is slightly out of date, but may be a good overview for you.
In your case, the following code will call [NSSpeechSynthesizer availableVoices]:
from AppKit import NSSpeechSynthesizer
NSSpeechSynthesizer.availableVoices()
which returns
(
"com.apple.speech.synthesis.voice.Agnes",
"com.apple.speech.synthesis.voice.Albert",
"com.apple.speech.synthesis.voice.Alex",
"com.apple.speech.synthesis.voice.BadNews",
"com.apple.speech.synthesis.voice.Bahh",
"com.apple.speech.synthesis.voice.Bells",
"com.apple.speech.synthesis.voice.Boing",
"com.apple.speech.synthesis.voice.Bruce",
"com.apple.speech.synthesis.voice.Bubbles",
"com.apple.speech.synthesis.voice.Cellos",
"com.apple.speech.synthesis.voice.Deranged",
"com.apple.speech.synthesis.voice.Fred",
"com.apple.speech.synthesis.voice.GoodNews",
"com.apple.speech.synthesis.voice.Hysterical",
"com.apple.speech.synthesis.voice.Junior",
"com.apple.speech.synthesis.voice.Kathy",
"com.apple.speech.synthesis.voice.Organ",
"com.apple.speech.synthesis.voice.Princess",
"com.apple.speech.synthesis.voice.Ralph",
"com.apple.speech.synthesis.voice.Trinoids",
"com.apple.speech.synthesis.voice.Vicki",
"com.apple.speech.synthesis.voice.Victoria",
"com.apple.speech.synthesis.voice.Whisper",
"com.apple.speech.synthesis.voice.Zarvox"
)
(a bridged NSCFArray) on my SL machine.
Mac OS X from 10.5 onward has shipped with Python and the objc module that will let you do what you want.
An example:
from Foundation import *
thing = NSKeyedUnarchiver.unarchiveObjectWithFile_(some_plist_file)
You can find more documentation here.
You probably want PyObjC. That said, I've never actually used it myself (I've only ever seen demos), so I'm not certain that it will do what you need.

Finding the Current Active Window in Mac OS X using Python

Is there a way to find the application name of the current active window at a given time on Mac OS X using Python?
This should work:
#!/usr/bin/python
from AppKit import NSWorkspace
activeAppName = NSWorkspace.sharedWorkspace().activeApplication()['NSApplicationName']
print activeAppName
Only works on Leopard, or on Tiger if you have PyObjC installed and happen to point at the right python binary in line one (not the case if you've installed universal MacPython, which you'd probably want to do on Tiger). But Peter's answer with the Carbon way of doing this will probably be quite a bit faster, since importing anything from AppKit in Python takes a while, or more accurately, importing something from AppKit for the first time in a Python process takes a while.
If you need this inside a PyObjC app, what I describe will work great and fast, since you only experience the lag of importing AppKit once. If you need this to work as a command-line tool, you'll notice the performance hit. If that's relevant to you, you're probably better off building a 10 line Foundation command line tool in Xcode using Peter's code as a starting point.
The method in the accepted answer was deprecated in OS X 10.7+. The current recommended version would be the following:
from AppKit import NSWorkspace
active_app_name = NSWorkspace.sharedWorkspace().frontmostApplication().localizedName()
print(active_app_name)
First off, do you want the window or the application name? This isn't Windows—an application process on Mac OS X can have multiple windows. (Furthermore, this has also been true of Windows for a few years now, although I have no idea what the API looks like for that.)
Second, Carbon or Cocoa?
To get the active window in Cocoa:
window = NSApp.mainWindow()
To get the name of your process in Cocoa:
appName = NSProcessInfo.processInfo().processName()
Edit: Oh, I think I know what you want. The name of the frontmost process, right?
I don't think there's a way to do it in Cocoa, but here's how to do it in Carbon in C:
ProcessSerialNumber psn = { 0L, 0L };
OSStatus err = GetFrontProcess(&psn);
/*error check*/
CFStringRef processName = NULL;
err = CopyProcessName(&psn, &processName);
/*error check*/
Remember to CFRelease(processName) when you're done with it.
I'm not sure what that will look like in Python, or if it's even possible. Python doesn't have pointers, which makes that tricky.
I know PyObjC would translate the latter argument to CopyProcessName into err, processName = CopyProcessName(…), but the Carbon bindings don't rely on PyObjC (they're part of core Python 2), and I'm not sure what you do about the PSN either way.
I needed the current frontmost application in a Python script that arranges the windows nicely on my screen (see move_window).
Of course, the complete credit goes to Peter! But here is the complete program:
#include <Carbon/Carbon.h>
int main(int, char) {
ProcessSerialNumber psn = { 0L, 0L };
OSStatus err = GetFrontProcess(&psn);
CFStringRef processName = NULL;
err = CopyProcessName(&psn, &processName);
printf("%s\n", CFStringGetCStringPtr(processName, NULL));
CFRelease(processName);
}
Build with gcc -framework Carbon filename.c

Categories