무효 클릭 IP 추적 중...
c#

C#에서 파이썬 파일 실행 시키는 방법 완벽정리(with Process)

꼬예 2023. 1. 3.

어떻게 python파일c#에서 실행시킬 수 있을까?

여러 방법이 있지만 이번에 소개할 내용은  [ic]Process()[/ic]를 이용한 방법이다.

 

1.예제 코드 준비 / 기본 컨셉

1) python코드

//test1.py

print('hello world\n  hello world2\n hello world3' )

 

2) C# 코드 

[ic]test1.py[/ic]를 c#에서 동작시켜 보겠다.

 

기본적으로 2가지 컨셉이 있다.

동작원리는 같지만 코드 형태가 조금 다르기 때문에 소개한다.

 

(1) [ic]Process()[/ic] 객체 생성방식

Process process = new Process();

[ic]Process[/ic] 객체를 생성한다.

 

// Set the file path of the Python executable
process.StartInfo.FileName = @"C:\Users\AppData\Local\Programs\Python\Python310\python.exe";

// Set the arguments for the Python script
process.StartInfo.Arguments = @"D:\pythonproject\detectionserver\test1.py";

[ic].StartInfo[/ic]를 통해 파이썬 명령어([ic].FileName[/ic])실행시킬 파일명([ic].Arguments[/ic])을 작성한다.

 

이때 python 실행 파일이 환경변수로 등록되어 있다면 python만 입력해도 무방하다.

process.StartInfo.FileName = @"python";

 

😀파이썬 파일을 실행할 때  [ic]'python 파일명'[/ic] 을 입력한다.
이는 환경변수로 등록되어 있었기 때문에 가능한 거다.

만약 등록되어 있지 않다면 파이썬 실행파일 full path를 작성해야 한다.
ex) "C:\Users\AppData\Local\Programs\Python\Python310\python.exe 파일명" 

 

process.Start();

//output 
/*
hello world
hello world2
hello world3
*/

[ic]process.Start()[/ic]를 통해 실행시켜 준다.

 

(2) [ic]ProcessStartInfo()[/ic] 객체 생성 방식

[ic]ProcessStartInfo()[/ic]객체 생성

ProcessStartInfo start = new ProcessStartInfo();

 

[ic]ProcessStartInfo[/ic] 객체에 있는 [ic]Filename[/ic], [ic]Arguments[/ic]값을 할당해 준다.

start.FileName = @"python";
start.Arguments = @"D:\pythonproject\detectionserver\test1.py";

 

여기서 차이점이 발생한다.

Process.Start(start);

[ic]Process.Start()[/ic] 인자로 [ic]ProcessStartInfo[/ic]객체를 넣어준다

 

 

지금까지는 python 출력값을 터미널창을 통해 확인해 봤다.

그 출력값을 c# 변수에 담아 사용할 순 없을까?

 

그때 등장하는 것이 [ic].RedirectStandardOutput[/ic]다.

 

2. [ic].RedirectStandardOutput[/ic] 사용법

출력 output을 리다이렉트 시키는 방법이다.

 

사용법은 간단한다.

[ic]process.StartInfo.RedirectStandardOutput = true;[/ic]로 설정해주면 된다.

 

// Set the file path of the Python executable
process.StartInfo.FileName = @"python";

// Set the arguments for the Python script
process.StartInfo.Arguments = @"D:\pythonproject\detectionserver\test1.py";

//Redirect the output of the process to the StandardOutput property
process.StartInfo.RedirectStandardOutput = true;

// Start the process
process.Start();

//output
/*
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='cp949'>
OSError: [Errno 22] Invalid argument
*/

 

하지만 이대로 실행하면 에러가 발생한다.

redirect 시킨다고 하였지만 목적 장소를 지정하지 않았기 때문이다. 

 

[ic]process.StandardOutput.ReadToEnd()[/ic]통해 redirect값을 받을 변수를 세팅해 준다.

// Set the file path of the Python executable
process.StartInfo.FileName = @"python";

// Set the arguments for the Python script
process.StartInfo.Arguments = @"D:\pythonproject\detectionserver\test1.py";

//Redirect the output of the process to the StandardOutput property
process.StartInfo.RedirectStandardOutput = true;

// Start the process
process.Start();

// Read the output of the process from the StandardOutput property
string output = process.StandardOutput.ReadToEnd();

// Do something with the output
Console.WriteLine(output);

//output
/*
hello world
hello world2
hello world3
*/

 

참고)
.ReadToEnd ⇒ output 처음부터 끝까지 읽어서 다 담겠다
.ReadLine ⇒ output 한 줄만 담겠다.

// .ReadLine 적용시 output은 전체줄이 아닌 1줄만 읽는다.
hello world
/*

 

output이 있다면 input도 있지 않을까?

 

[ic]RedirectStandardInput[/ic]는 input값을 python코드로 주입할 때 사용된다.

 

3. [ic].RedirectStandardInput[/ic] 사용법

1) python코드

//test1.py

[ic]input()[/ic]함수를 통해 c#에서 넘어올 input값을 대기한다.

# Read input from the standard input stream
input_string = input()

# Process the input
print("You entered:", input_string)

 

2) c# 코드

[ic]process.StartInfo.RedirectStandardInput = true;[/ic] 설정한다.

process.StartInfo.FileName = @"python";

process.StartInfo.Arguments = @"D:\pythonproject\detectionserver\test1.py";

process.StartInfo.RedirectStandardInput = true;

process.Start();

process.StandardInput.WriteLine("Hello world to python");
process.StandardInput.Flush();
process.StandardInput.Close();


//output
// You entered: Hello world to python1
process.StandardInput.WriteLine  input으로 넣을 값을 작성한다.
process.StandardInput.Flush() input으로 넣은 값은 일시적으로 buffer에 저장된다.
이 buffer에 저장된 값을 python input값으로 (확실하게) 넘겨주는 역할을 하는 것이 Flush()다.
process.StandardInput.Close() input 작업을 마친다고 알려주는 코드다.

 

실수 주의😭

[ic]process.Start()[/ic] 위치를 잘 기억하자. 제일 뒤에 오면 오류가 발생한다.

process.Start() 위치 주의

 

 

intput값으로 두 개 이상을 넣고 싶다면 어떻게 할까?

4. input으로 두개 이상 넣기

 

//c# 코드

process.StartInfo.FileName = @"python";

process.StartInfo.Arguments = @"D:\pythonproject\detectionserver\test1.py";

process.StartInfo.RedirectStandardInput = true;
process.Start();

process.StandardInput.WriteLine("Hello world to python1");
process.StandardInput.WriteLine("Hello world to python2");

process.StandardInput.Close();

[ic].WriteLine[/ic]를  두 개 이상 작성하면 된다

 

//python 코드

# Read input from the standard input stream
lines = []
while True:
    try:
        line = input()
        lines.append(line)
    except EOFError:
        break

# Process the input
print("You entered:")
for line in lines:
    print(line)

다만  input()을 여러 번 받아야 하므로 파이썬 코드 수정이 필요하다. 

그런데 좀 번거롭다.

 

그래서 다른 방식을 소개한다.

 

//c# 코드

process.StartInfo.FileName = @"python";

process.StartInfo.Arguments = @"D:\pythonproject\detectionserver\test1.py ""Hello world to python1"" ""Hello world to python2"" ";

process.Start();

[ic]RedirectStandardInput[/ic] 를 지운다.

그리고 [ic].Arguments[/ic]에 input으로 사용할 값을 추가해 준다.

 

""는 각 인자별로 구분해주기 용도다.

안 넣어주면 space마다 input으로 인식을 해버린다.

 

예를 들어 'Hello world to python1' 를 넣으면 Hello, world, to, python1과 같이 input을 4개로 인식한다.

 

c# 코드 변경에 따라 python 코드 변경도 필요하다.

import sys

print(sys.argv)
arg1, arg2 = sys.argv[1], sys.argv[2]

#ouput
'''
["D:\pythonproject\detectionserver\test1.py","Hello world to python1,"Hello world to python2"]
'''

[ic]sys.argv[/ic]는 [ic]process.StartInfo.Arguments[/ic]에 담긴 값을 리스트형태로 가지고 있다.

이 중 0번째 값은 파이썬 파일 실행경로이고 1, 2번째가  input값이다.

 

 

5) [ic]process.WaitforExit();[/ic]

[ic]process.WaitforExit();[/ic] 는 이전 process 작업이 완전히 끝날 때까지 기다려주는 함수다.

process.StartInfo.FileName = @"C:\Users\AppData\Local\Programs\Python\Python310\python.exe";

// Set the arguments for the Python script
process.StartInfo.Arguments = @"D:\pythonproject\detectionserver\test1.py";

//Redirect the output of the process to the StandardOutput property
process.StartInfo.RedirectStandardOutput = true;

// Start the process
process.Start();

//////////////////////////////////////////////////////////////////////////////////
///////////////// 위 작업이 끝날때까지 기다리기 /////////////////////////////////
process.WaitForExit();

//////////////////////////////////////////////////////////////////////////
// Read the output of the process from the StandardOutput property
string output = process.StandardOutput.ReadToEnd();

// Do something with the output
Console.WriteLine(output);

 

시간이 오래 걸리는 작업일 경우 기다리지 않고 output을 받으려고 하면 오류가 발생한다.

이때 [ic]process.WaitforExit();[/ic] 는 유용한 함수다.

 

FAQ)

Q) 파이썬 파일을 가상환경 상태에서 실행하고 싶다면?

Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.RedirectStandardInput = true;

process.Start();

process.StandardInput.WriteLine(@"D:\pythonproject\detectionserver\venv\Scripts\activate.bat");
process.StandardInput.WriteLine(@$"python D:\pythonproject\detectionserver\test1.py");
process.StandardInput.Flush();
process.StandardInput.Close();

이때는 다이렉트로 파일을 실행시키기보다 cmd를 통한 방법이 좋다.

 

원리는 같다. cmd창을 열고 input값을 통해 값을 입력하면 된다.

 

참고로 'D:\pythonproject\detectionserver\venv\Scripts\activate.bat' 은 가상환경 실행파일의 절대경로다.

activate.bat 경로

 

Q) 터미널 창이 뜨는게 보기싫다. 끄고 싶다면?

[ic]process.StartInfo.CreateNoWindow[/ic]를 true로 설정하면된다.

process.StartInfo.CreateNoWindow = true;
  • 트위터 공유하기
  • 페이스북 공유하기
  • 카카오톡 공유하기
이 컨텐츠가 마음에 드셨다면 커피 한잔(후원) ☕

댓글