交互式绘图无法使用从另一个程序通过管道传递的输入进行初始化

eep

我编写了一个Python脚本,该脚本应该运行一个循环,该循环从标准输入中读取3d坐标,并在上以散点图的形式显示最近读取的坐标mpl_toolkits.mplot3d.Axes3D

当我通过提示符手动输入坐标时,它可以工作(尽管会给出一些弃用警告):

$ python plot3d.py
.5 .5 .5
/usr/lib/pymodules/python2.7/matplotlib/backend_bases.py:2407: MatplotlibDeprecationWarning: Using default event loop until function specific to this GUI is implemented
  warnings.warn(str, mplDeprecation)

当我将文件中的坐标输入程序时,它也可以工作:

$ head generated
0.56 0.40 0.55
0.61 0.49 0.60
0.48 0.39 0.48
0.39 0.33 0.39
0.32 0.28 0.32
0.35 0.31 0.35
0.50 0.47 0.50
0.40 0.38 0.40
0.37 0.35 0.37
0.51 0.50 0.51
$ python plot3d.py < generated

但是,当我将生成脚本的输出直接通过管道传递到绘图脚本时,它不起作用,并且生成脚本time.sleep()在每次迭代之后执行一个

$ python generate3d.py | python plot3d.py

工作行为是,打开图形窗口,该窗口显示一个散点图,该散点图显示一个点。不起作用是,图形窗口已打开,但仅显示灰色背景,没有轴或点。

这是绘图脚本的代码:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

plt.ion()

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

plotted_items = None
while True:
    if plotted_items is not None:
        plotted_items.remove()
    try:
        x,y,z = map(float, raw_input().split())
    except:
        break
    else:
        plotted_items = ax.scatter([x],[y],[z])
        ax.set_xlim(-5, 5)
        ax.set_ylim(-5, 5)
        ax.set_zlim(-5, 5)
        plt.pause(0.1)

这是生成脚本的代码:

from random import random
import time

last = None
while True:
    if last is None:
        last = [random(), random(), random()]
    offset = random()
    for i in range(len(last)):
        last[i] += 0.25 * (offset - last[i])
    print "%.2f %.2f %.2f" % tuple(last)
    # the value of this sleep duration influences how long it takes to initialize
    # the plot in the other script!?
    time.sleep(0.5) 

我观察到睡眠时间在生成脚本中的影响可能与轴初始化所需的时间成正比。睡眠时间接近于零时,几乎不需要初始化时间。睡眠时间为0.1时,图表需要花费一些时间。我还没有探索显示数据最终何时存在的延迟。

任何人都可以重现这种行为吗?谁能帮助我了解和解决此问题?难道我做错了什么?

可能有用的信息:

$ lsb_release -d
Description:    Ubuntu 14.04.5 LTS
$ python --version
Python 2.7.6

>>> matplotlib.__version__
'1.3.1'
埃德·史密斯

我可以使用matplotlib版本1.4.3和python 2.7复制。原因似乎是由于pythonstdin读取函数阻塞直到管道关闭(此处所述),

这个问题的根源在于在Python中实现这些阅读机制的方式(请参阅Python的问题跟踪器中有关此问题讨论)。在Python 2.7.6中,实现依赖于C的stdio库。

他们在链接中使用的解决方案是geneate3d.py作为子进程运行并设置非阻塞标志,

from subprocess import Popen, PIPE
import time
from fcntl import fcntl, F_GETFL, F_SETFL
from os import O_NONBLOCK, read

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import sys

plt.ion()

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# run the shell as a subprocess:
p = Popen(['python', 'generate3d.py'],
        stdin = PIPE, stdout = PIPE, stderr = PIPE, shell = False)
# set the O_NONBLOCK flag of p.stdout file descriptor:
flags = fcntl(p.stdout, F_GETFL) # get current p.stdout flags
fcntl(p.stdout, F_SETFL, flags | O_NONBLOCK)
# issue command:
p.stdin.write('command\n')
# let the shell output the result:
time.sleep(0.1)

plotted_items = None
while True:
    if plotted_items is not None:
        try:
            plotted_items.remove()
        except ValueError:
            print(plotted_items)
            pass
    try:
        x,y,z = map(float, read(p.stdout.fileno(), 1024).split(' '))
    except OSError:
        time.sleep(0.5) 
    except:
        raise
    else:
        plotted_items = ax.scatter([x],[y],[z])
        ax.set_xlim(-5, 5)
        ax.set_ylim(-5, 5)
        ax.set_zlim(-5, 5)
        plt.pause(0.1)
        plt.draw()

您需要sys.stdout.flush()在中打印后添加generate3d.py

现在看来似乎应该是可以设置O_NONBLOCK标志sys.stdin的东西,如flags = fcntl(sys.stdin, F_GETFL)fcntl(sys.stdin, F_SETFL, flags | O_NONBLOCK)但是,这对我不起作用。根据错误跟踪器,我认为这在python 3.0中不再是问题

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何通过管道将数据传送到交互式bash脚本并将管道输出到另一个命令?

来自分类Dev

从另一个程序交互式调试python代码

来自分类Dev

无法初始化向量来保存使用其构造函数初始化的另一个类

来自分类Dev

快速全局常量:不能使用另一个常量进行初始化

来自分类Dev

将Ruby对象的实例变量作为映射传递给另一个类的初始化程序

来自分类Dev

“便捷初始化程序缺少对另一个初始化程序的'自我'调用”

来自分类Dev

“便利初始化程序缺少对另一个初始化程序的'自我'调用”

来自分类Dev

Java-试图使用在另一个类中传递给另一个构造函数的参数来初始化对象?

来自分类Dev

在 Python 中使用另一个对象初始化一个对象

来自分类Dev

在初始化期间在另一个常量中使用一个常量

来自分类Dev

如何在Rust的初始化列表中通过另一个值初始化值?

来自分类Dev

使用交互式绘图仅在Altair中缩放一个轴

来自分类Dev

是否可以保证在另一个类使用静态集合之前对其进行初始化/填充?

来自分类Dev

C# - 我似乎无法将数组传递给不同的方法,一个用于初始化,另一个用于修改?

来自分类Dev

调用另一个类初始化程序时如何处理错误?

来自分类Dev

如何获得bash脚本来响应另一个交互式脚本?

来自分类Dev

如何获得另一个非root用户的交互式shell?

来自分类Dev

如何获得另一个非root用户的交互式shell?

来自分类Dev

如何以另一个用户身份运行交互式命令

来自分类Dev

当另一个打开的c#winforms时使窗体不交互式

来自分类Dev

另一个Shell脚本内的背景中的交互式Shell

来自分类Dev

使用另一个构造函数的初始化来初始化构造函数中的属性

来自分类Dev

如何通过另一个类更新/更改一个类的初始化参数?

来自分类Dev

使用张量流使用另一个变量初始化变量

来自分类Dev

如何使用“ coproc”与另一个命令驱动程序进行交互

来自分类Dev

使用OS X的情节提要板初始化另一个窗口

来自分类常见问题

在特定位置初始化另一个数组时使用数组

来自分类Dev

CLOS:使用插槽值初始化另一个插槽

来自分类Dev

使用依赖于另一个属性的属性初始化对象

Related 相关文章

  1. 1

    如何通过管道将数据传送到交互式bash脚本并将管道输出到另一个命令?

  2. 2

    从另一个程序交互式调试python代码

  3. 3

    无法初始化向量来保存使用其构造函数初始化的另一个类

  4. 4

    快速全局常量:不能使用另一个常量进行初始化

  5. 5

    将Ruby对象的实例变量作为映射传递给另一个类的初始化程序

  6. 6

    “便捷初始化程序缺少对另一个初始化程序的'自我'调用”

  7. 7

    “便利初始化程序缺少对另一个初始化程序的'自我'调用”

  8. 8

    Java-试图使用在另一个类中传递给另一个构造函数的参数来初始化对象?

  9. 9

    在 Python 中使用另一个对象初始化一个对象

  10. 10

    在初始化期间在另一个常量中使用一个常量

  11. 11

    如何在Rust的初始化列表中通过另一个值初始化值?

  12. 12

    使用交互式绘图仅在Altair中缩放一个轴

  13. 13

    是否可以保证在另一个类使用静态集合之前对其进行初始化/填充?

  14. 14

    C# - 我似乎无法将数组传递给不同的方法,一个用于初始化,另一个用于修改?

  15. 15

    调用另一个类初始化程序时如何处理错误?

  16. 16

    如何获得bash脚本来响应另一个交互式脚本?

  17. 17

    如何获得另一个非root用户的交互式shell?

  18. 18

    如何获得另一个非root用户的交互式shell?

  19. 19

    如何以另一个用户身份运行交互式命令

  20. 20

    当另一个打开的c#winforms时使窗体不交互式

  21. 21

    另一个Shell脚本内的背景中的交互式Shell

  22. 22

    使用另一个构造函数的初始化来初始化构造函数中的属性

  23. 23

    如何通过另一个类更新/更改一个类的初始化参数?

  24. 24

    使用张量流使用另一个变量初始化变量

  25. 25

    如何使用“ coproc”与另一个命令驱动程序进行交互

  26. 26

    使用OS X的情节提要板初始化另一个窗口

  27. 27

    在特定位置初始化另一个数组时使用数组

  28. 28

    CLOS:使用插槽值初始化另一个插槽

  29. 29

    使用依赖于另一个属性的属性初始化对象

热门标签

归档