Python: Multithreading between Java subproccess and Python listener?

TheMountainFurnaceGabriel

I am monitoring and Minecraft server and I am making a setup file in Python. I need to be able to run two threads, one running the minecraft_server.jar in the console window, while a second thread is constantly checking the output of the minecraft_server. Also, how would I input into the console from Python after starting the Java process?

Example:

thread1 = threading.Thread(target=listener)
thread2 = minecraft_server.jar

def listener():
    if minecraft_server.jarOutput == "Server can't keep up!":
        sendToTheJavaProccessAsUserInputSomeCommandsToRestartTheServer
abarnert

It's pretty hard to tell here, but I think what you're asking is how to:

  • Launch a program in the background.
  • Send it input, as if it came from a user on the console.
  • Read its output that it tries to display to a user on the console.
  • At the same time, run another thread that does other stuff.

The last one is pretty easy; in fact, you've mostly written it, you just need to add a thread1.start() somewhere.

The subprocess module lets you launch a program and control its input and output. It's easiest if you want to just feed in all the input at once, wait until it's done, then process all the output, but obviously that's not your case here, so it's a bit more involved:

minecraft = subprocess.Popen(['java', 'path/to/minecraft_server.jar', '-other', 'args],
                             stdin=subprocess.PIPE, 
                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

stdout과 stderr을 하나로 병합하고 있습니다. 개별적으로 읽거나 stderr을 / dev / null로 보내려면 문서를 참조하십시오. 모두 매우 간단합니다. 여기서 가정하는 동안 minecraft_server모든 명령, 모든 응답 및 모든 정보 메시지가 정확히 한 줄 (즉, a로 끝나는 1K 미만의 텍스트 \n) 인 간단한 줄 기반 프로토콜 사용 한다고 가정합니다. .

이제 입력을 보내려면 다음과 같이하십시오.

minecraft.stdin.write('Make me a sandwich\n')

또는 Python 3.x에서 :

minecraft.stdin.write(b'Make me a sandwich\n')

출력을 읽으려면 다음을 수행하십시오.

response = minecraft.stdout.readline()

That works just like a regular file. But note that it works like a binary file. In Python 2.x, the only difference is that newlines don't get automatically converted, but in Python 3.x, it means you can only write bytes (and compatible objects), not strs, and you will receive bytes back. There are good reasons for that, but if you want to get pipes that act like text files instead, see the universal_newlines (and possibly bufsize) arguments under Frequently Used Arguments and Popen Constructor.


Also, it works like a blocking file. With a regular file, this rarely matters, but with a pipe, it's quite possible that there will be data later, but there isn't data yet (because the server hasn't written it yet). So, if there is no output yet (or not a complete line's worth, since I used readline()), your thread just blocks, waiting until there is.

If you don't want that, you probably want to create another thread to service stdout. And its function can actually look pretty similar to what you've got:

def listener():
    for line in minecraft.stdout:
        if line.strip() == "Server can't keep up!":
            minecraft.stdin.write("Restart Universe\n")

Now that thread can block all day and there's no problem, because your other threads are still going.


Well, not quite no problem.

First it's going to be hard to cleanly shut down your program.

More seriously, the pipes between processes have a fixed size; if you don't service stdout fast enough, or the child doesn't service stdin fast enough, the pipe can block. And, the way I've written things, if the stdin pipe blocks, we'll be blocked forever in that stdin.write and won't get to the next read off stdout, so that can block too, and suddenly we're both waiting on each other forever.

You can solve this by having another thread to service stdout. The subprocess module itself includes an example, in the Popen._communicate function used by all the higher-level functions. (Make sure to look at Python 3.3 or later, because earlier versions had bugs.)

Python 3.4 이상 (또는 PyPI에서 백 포트가없는 3.3)을 사용하는 경우 대신를 사용 asyncio하여 이벤트 루프를 중심으로 프로그램을 다시 작성하고 리액터 기반 네트워크 서버를 작성하는 것과 동일한 방식으로 입력 및 출력을 처리 할 수 ​​있습니다. 그게 2017 년에 멋진 아이들이하는 일이지만 2014 년 말에 많은 사람들은 여전히 ​​새롭고 무섭다고 생각했습니다.


이 모든 것이 귀하가 서명 한 것보다 훨씬 더 많은 작업처럼 들린다면 pexpect, 지루한 세부 사항을 많이 정리하고 귀하의 경우에 사실 일 수있는 몇 가지 단순화 된 가정을 만드는를 사용하는 것이 좋습니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

python subproccess.check_output 및 adb logcat과 함께 grep 사용

분류에서Dev

how to fix python script (email-listener)

분류에서Dev

Opencv Python Multithreading으로 비디오 녹화

분류에서Dev

Java multithreading errors handling

분류에서Dev

Multithreading with sockets JAVA

분류에서Dev

Java multithreading, weird things

분류에서Dev

Java Listener- not listening

분류에서Dev

Java handling multiple clients - multithreading?

분류에서Dev

Java handling multiple clients - multithreading?

분류에서Dev

Java Multithreading null pointer exception

분류에서Dev

Speed of Java and Python implementation

분류에서Dev

Porting XGBoost model between Python and R

분류에서Dev

What's the difference between @ and * with python matrix multiplication?

분류에서Dev

In python, what is the difference between MemoryError and OverflowError?

분류에서Dev

how to delete lines between specific signs in python?

분류에서Dev

Value conversion between ctypes and python is wrong

분류에서Dev

Behaviour of rotating image between Kivy and Python

분류에서Dev

Remove reference to Python class between unittests

분류에서Dev

Passing structure between Python and C using SWIG

분류에서Dev

Share python package between appengine modules

분류에서Dev

Difference between two values in txt file, python

분류에서Dev

Java Multithreading 읽기 정보

분류에서Dev

Run Java Molecular Dynamic simulation program in multithreading

분류에서Dev

java.lang.NullPointerException : On Button Click Listener

분류에서Dev

How to remove an "mouseup" event listener in Java Script

분류에서Dev

Symfony2 User roles vanish between Listener and UserProvider

분류에서Dev

How do I communicate variables between methods in Python?

분류에서Dev

Python Write lines of a text in between a range of numbers to a new file

분류에서Dev

SFTP using Python Paramiko directly between two remote machines

Related 관련 기사

  1. 1

    python subproccess.check_output 및 adb logcat과 함께 grep 사용

  2. 2

    how to fix python script (email-listener)

  3. 3

    Opencv Python Multithreading으로 비디오 녹화

  4. 4

    Java multithreading errors handling

  5. 5

    Multithreading with sockets JAVA

  6. 6

    Java multithreading, weird things

  7. 7

    Java Listener- not listening

  8. 8

    Java handling multiple clients - multithreading?

  9. 9

    Java handling multiple clients - multithreading?

  10. 10

    Java Multithreading null pointer exception

  11. 11

    Speed of Java and Python implementation

  12. 12

    Porting XGBoost model between Python and R

  13. 13

    What's the difference between @ and * with python matrix multiplication?

  14. 14

    In python, what is the difference between MemoryError and OverflowError?

  15. 15

    how to delete lines between specific signs in python?

  16. 16

    Value conversion between ctypes and python is wrong

  17. 17

    Behaviour of rotating image between Kivy and Python

  18. 18

    Remove reference to Python class between unittests

  19. 19

    Passing structure between Python and C using SWIG

  20. 20

    Share python package between appengine modules

  21. 21

    Difference between two values in txt file, python

  22. 22

    Java Multithreading 읽기 정보

  23. 23

    Run Java Molecular Dynamic simulation program in multithreading

  24. 24

    java.lang.NullPointerException : On Button Click Listener

  25. 25

    How to remove an "mouseup" event listener in Java Script

  26. 26

    Symfony2 User roles vanish between Listener and UserProvider

  27. 27

    How do I communicate variables between methods in Python?

  28. 28

    Python Write lines of a text in between a range of numbers to a new file

  29. 29

    SFTP using Python Paramiko directly between two remote machines

뜨겁다태그

보관