0

is it possible to store the output of a .py file in a swift variable? In my xcode project I have put a python script. I run this script using this code

class ViewController: NSViewController {
    var pathForFile = Bundle.main.path(forResource: "eject", ofType: "py")
    let path = "/usr/bin/python/"
        
    override func viewDidLoad() {
            
            let arguments = [pathForFile]
            let task = Process.launchedProcess(launchPath: path, arguments: arguments as! [String])
            task.waitUntilExit()
            super.viewDidLoad()

        }
}

If I put print(x) in the python file, once executed I can see the x value on the output window of xcode.
I also tried to put return x in the main function and then tried to set let y = task.waitUntilExit() in the swift file, but the only thing I get is an empty variable

I don't know much about swift, so please forgive my lack of knowledge. Thanks in advance!

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
Jacopo
  • 99
  • 1
  • 8
  • Should there be a trailing `/` on this line? `let path = "/usr/bin/python/"` – Tom Dalton Jan 21 '22 at 15:30
  • 1
    Does this answer your question? [Swift: How to read standard output in a child process without waiting for process to finish](https://stackoverflow.com/questions/33820746/swift-how-to-read-standard-output-in-a-child-process-without-waiting-for-proces) – Willeke Jan 22 '22 at 05:57
  • @Willeke Not really, but it helped me out. Now I'll post the answer i found, thanks by the way! – Jacopo Jan 23 '22 at 11:33

1 Answers1

1

Solution

As explained in this page
https://www.hackingwithswift.com/example-code/system/how-to-run-an-external-program-using-process
and shown in the answer suggested by Willeke, you can use Pipe() to do that.
I changed the code as shown below.

override func viewDidLoad() {
    super.viewDidLoad()
    let task = Process()
    task.executableURL = URL(fileURLWithPath: "/usr/bin/python")
    let filename = Bundle.main.path(forResource: "eject", ofType: "py")
    task.arguments = [filename!]
    let outputPipe = Pipe()
    task.standardOutput = outputPipe
    
       do{
           try task.run()
       } catch {
           print("error")
       }
    
    let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(decoding: outputData, as: UTF8.self)
    print(output)
    
   }

Be sure to put this

let outputPipe = Pipe()
task.standardOutput = outputPipe

before the task.run() command and this

let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
let output = String(decoding: outputData, as: UTF8.self)
print(output)

after it.

Jacopo
  • 99
  • 1
  • 8