21

私は、計算後にgnuplot入力としてフォーマットされた2つのデータファイルを生成するPythonスクリプトを持っています。

Python から gnuplot を「呼び出す」にはどうすればよいですか?

次の python 文字列を gnuplot への入力として送信したい:

"plot '%s' with lines, '%s' with points;" % (eout,nout)

ここで、' eout ' と' nout 'は 2 つのファイル名です。

PS:追加の python モジュール (gnuplot-py など) は使用せず、標準 API のみを使用することを好みます。

ありがとうございました

4

8 に答える 8

23

このsubprocessモジュールを使用すると、他のプログラムを呼び出すことができます。

import subprocess
plot = subprocess.Popen(['gnuplot'], stdin=subprocess.PIPE)
plot.communicate("plot '%s' with lines, '%s' with points;" % (eout,nout))
于 2010-01-29T12:48:52.320 に答える
16

サブプロセスは、Doug Hellemann の Python Module of the Week で非常に明確に説明されています。

これはうまくいきます:

import subprocess
proc = subprocess.Popen(['gnuplot','-p'], 
                        shell=True,
                        stdin=subprocess.PIPE,
                        )
proc.stdin.write('set xrange [0:10]; set yrange [-2:2]\n')
proc.stdin.write('plot sin(x)\n')
proc.stdin.write('quit\n') #close the gnuplot window

'communicate' を使用することもできますが、gnuplot の一時停止コマンドを使用しない限り、プロット ウィンドウはすぐに閉じます。

proc.communicate("""
set xrange [0:10]; set yrange [-2:2]
plot sin(x)
pause 4
""")
于 2011-02-15T10:43:21.283 に答える
10

簡単な方法は、gnuplot コマンドを含む 3 番目のファイルを作成し、Python にそのファイルで gnuplot を実行するように指示することです。あなたが書くと言う

"plot '%s' with lines, '%s' with points;" % (eout,nout)

tmp.gp というファイルに。次に、使用できます

from os import system, remove
system('gnuplot -persist tmp.gp')
remove('tmp.gp')
于 2010-01-29T13:11:02.283 に答える
7

私は似たようなことをしようとしていましたが、さらにPython内からデータをフィードし、グラフファイルを変数として出力したかったのです(データもグラフも実際のファイルではありません)。これは私が思いついたものです:

#! /usr/bin/env python

import subprocess
from sys import stdout, stderr
from os import linesep as nl

def gnuplot_ExecuteCommands(commands, data):
    args = ["gnuplot", "-e", (";".join([str(c) for c in commands]))]
    program = subprocess.Popen(\
        args, \
        stdin=subprocess.PIPE, \
        stdout=subprocess.PIPE, \
        stderr=subprocess.PIPE, \
        )
    for line in data:
        program.stdin.write(str(line)+nl)
    return program

def gnuplot_GifTest():
    commands = [\
        "set datafile separator ','",\
        "set terminal gif",\
        "set output",\
        "plot '-' using 1:2 with linespoints, '' using 1:2 with linespoints",\
        ]
    data = [\
        "1,1",\
        "2,2",\
        "3,5",\
        "4,2",\
        "5,1",\
        "e",\
        "1,5",\
        "2,4",\
        "3,1",\
        "4,4",\
        "5,5",\
        "e",\
        ]
    return (commands, data)

if __name__=="__main__":
    (commands, data) = gnuplot_GifTest()
    plotProg = gnuplot_ExecuteCommands(commands, data)
    (out, err) = (plotProg.stdout, plotProg.stderr)
    stdout.write(out.read())

そのスクリプトは、グラフをmainの最後のステップとして stdout にダンプします。同等のコマンド ライン (グラフが「out.gif」にパイプされる場所) は次のようになります。

gnuplot -e "set datafile separator ','; set terminal gif; set output; plot '-' using 1:2 with linespoints, '' using 1:2 with linespoints" > out.gif
1,1
2,2
3,5
4,2
5,1
e
1,5
2,4
3,1
4,4
5,5
e
于 2011-04-22T13:23:42.810 に答える
3

wgnuplot.exe へのインターフェイスを提供するクラスを次に示します。

from ctypes import *
import time
import sys
import os

#
# some win32 constants
#
WM_CHAR     = 0X0102
WM_CLOSE    = 16
SW_HIDE     = 0
STARTF_USESHOWWINDOW = 1

WORD    = c_ushort
DWORD   = c_ulong
LPBYTE  = POINTER(c_ubyte)
LPTSTR  = POINTER(c_char) 
HANDLE  = c_void_p

class STARTUPINFO(Structure):
    _fields_ = [("cb",DWORD),
        ("lpReserved",LPTSTR), 
        ("lpDesktop", LPTSTR),
        ("lpTitle", LPTSTR),
        ("dwX", DWORD),
        ("dwY", DWORD),
        ("dwXSize", DWORD),
        ("dwYSize", DWORD),
        ("dwXCountChars", DWORD),
        ("dwYCountChars", DWORD),
        ("dwFillAttribute", DWORD),
        ("dwFlags", DWORD),
        ("wShowWindow", WORD),
        ("cbReserved2", WORD),
        ("lpReserved2", LPBYTE),
        ("hStdInput", HANDLE),
        ("hStdOutput", HANDLE),
        ("hStdError", HANDLE),]

class PROCESS_INFORMATION(Structure):
    _fields_ = [("hProcess", HANDLE),
        ("hThread", HANDLE),
        ("dwProcessId", DWORD),
        ("dwThreadId", DWORD),]

#
# Gnuplot
#
class Gnuplot:
    #
    # __init__
    #
    def __init__(self, path_to_exe):
        # open gnuplot
        self.launch(path_to_exe)
        # wait till it's ready
        if(windll.user32.WaitForInputIdle(self.hProcess, 1000)):
            print "Error: Gnuplot timeout!"
            sys.exit(1)
        # get window handles
        self.hwndParent = windll.user32.FindWindowA(None, 'gnuplot')
        self.hwndText = windll.user32.FindWindowExA(self.hwndParent, None, 'wgnuplot_text', None)



    #
    # __del__
    #
    def __del__(self):
        windll.kernel32.CloseHandle(self.hProcess);
        windll.kernel32.CloseHandle(self.hThread);
        windll.user32.PostMessageA(self.hwndParent, WM_CLOSE, 0, 0)


    #
    # launch
    #
    def launch(self, path_to_exe):
        startupinfo = STARTUPINFO()
        process_information = PROCESS_INFORMATION()

        startupinfo.dwFlags = STARTF_USESHOWWINDOW
        startupinfo.wShowWindow = SW_HIDE

        if windll.kernel32.CreateProcessA(path_to_exe, None, None, None, False, 0, None, None, byref(startupinfo), byref(process_information)):
            self.hProcess = process_information.hProcess
            self.hThread = process_information.hThread
        else:
            print "Error: Create Process - Error code: ", windll.kernel32.GetLastError()
            sys.exit(1)



    #
    # execute
    #
    def execute(self, script, file_path):
        # make sure file doesn't exist
        try: os.unlink(file_path)
        except: pass

        # send script to gnuplot window
        for c in script: windll.user32.PostMessageA(self.hwndText, WM_CHAR, ord(c), 1L)

        # wait till gnuplot generates the chart
        while( not (os.path.exists(file_path) and (os.path.getsize(file_path) > 0))): time.sleep(0.01)
于 2011-06-15T11:09:46.250 に答える
2

少し遅れましたが、機能させるのに時間がかかったので、メモを入れる価値があるかもしれません。プログラムは、Windows 上の Python 3.3.2 で動作しています。

文字列ではなく、どこでもバイトが使用されていることに注意してください (たとえば、単に "plot x" ではなく、b"plot x")。ただし、問題がある場合は、単に次のようにします。

"plot x".encode("ascii")

最初の解決策:通信を使用してすべてを送信し、完了したら閉じます。一時停止を忘れてはなりません。そうしないと、ウィンドウがすぐに閉じられます。ただし、gnuplot を使用して画像をファイルに保存する場合は問題ありません。

from subprocess import *
path = "C:\\app\\gnuplot\\bin\\gnuplot"
p = Popen([path], stdin=PIPE, stdout=PIPE)
p.communicate(b"splot x*y\npause 4\n")

2 番目の解決策: stdin.write(...) を使用して、コマンドを次々に送信します。ただし、flush を忘れないでください。(これは最初はうまくいきませんでした) そして、terminateを使って接続を閉じ、仕事が終わったら gnuplot を使います。

from subprocess import *
path = "C:\\app\\gnuplot\\bin\\gnuplot"
p = Popen([path], stdin=PIPE, stdout=PIPE)

p.stdin.write(b"splot x*y\n")
p.stdin.flush()
...
p.stdin.write(b"plot x,x*x\n")
p.stdin.flush()
...
p.terminate()
于 2013-08-07T08:27:25.883 に答える