pytorch 使用两个Python版本要求冲突的库?

roqulrg3  于 2022-11-09  发布在  Python
关注(0)|答案(1)|浏览(319)

我有两个Python库需要在同一个环境中运行,它们是pptktorch-scatter,并且没有重叠的Python版本要求; pptk〈= 3.7和torch-scatter〉= 3.8。它们都在一定程度上大量使用C++来增强它们的功能,我怀疑我是否具备为所需的Python版本更新/降级它们所需的技术技能。
假设pptk是一个绘图库,我看到的唯一解决方案是创建一个Python 3.8环境并安装torch-scatter。然后编写一个脚本来获取我希望提供给pptk显示的任何数据,将其pickle到NamedTemporaryFile。最后启动一个新进程并将文件名作为参数传递给它。该进程将运行一个安装了pptk的Python 3.7环境,加载文件并显示数据。

**是否有比描述的更简单的解决方案?**Python中是否有一些支持调用不同的Python版本库并执行一些自动编组?

dsekswqp

dsekswqp1#

如果没有其他人提供更好的解决方案,并且将来有人在这里绊倒,这里是我实现的WYSIWYG解决方案。
函数pptk_subprocess接受我显示的数据,执行一些操作,并将其写入NamedTemporaryFile。然后将文件名传递到commands字符串中。该字符串启动pptk库所在的Anaconda环境,并在该环境中运行当前的__file__。在__main__中,这个文件被加载,数据被读取以显示。还有一个选项,通过相同的NamedTemporaryFile x x x x 8n1x数据将一些数据写回到pptk_subprocess“上下文”中。
此解决方案似乎只能从命令行运行,而不能通过IDE的run功能运行。

import os
import sys
import math
import time
import shutil
import tempfile
import subprocess
import numpy as np

import matplotlib.image as mpimg
from matplotlib.colors import ListedColormap

"""
Python 3.7 functions
"""
def subprocess_pptk_lidar_image(points, labels):
    import pptk
    """
    Plot a point cloud with pptk and return a TemporaryFile of a screenshot
    Note: User MUST .CLOSE() the file.
    """

    # Continually attempt to open pptk, plot, and capture an image. pptk sometimes selects a port in use.
    tmpimg = None
    got_image = False
    num_tries = 0
    while not got_image:
        if num_tries > 10:
            raise RuntimeError(f'Attempted to open pptk 10 times. Something is wrong.')

        tmpimg = tempfile.NamedTemporaryFile(suffix='.png', delete=False)
        try:
            v = pptk.viewer(points)
            v.attributes(labels)
            v.set(point_size=0.02)
            v.set(r=500)
            v.set(phi=math.radians(90))
            v.set(theta=math.radians(65))
            v.capture(tmpimg.name)
            time.sleep(1.5)
            got_image = True
        except Exception as e:
            num_tries += 1
            continue
    return tmpimg

def subprocess_interactive_lidar_pptk(points, labels):
    import pptk
    v = pptk.viewer(points[:, 0:3])
    v.attributes(labels)
    v.set(point_size=0.05)
    v.wait()  # Wait until the user hits enter.

"""
Python 3.8 functions
"""
def generate_colormap_from_labels_colors(labels: dict, colors: dict):
    """
    Given a dictionary of labels {int: 'label'} and colors {int: 'color'} generate a ColorMap
    """
    # If there is a label 'unclassified' label ensure its color is 'WhiteSmoke' and not 'Black'
    if 'unclassified' in labels.values():
        # Get the index of the unclassified label in the label_dict
        unclass_index = list(labels.keys())[list(labels.values()).index('unclassified')]
        colors[unclass_index] = 'WhiteSmoke'

    color_map = ListedColormap(colors.values())
    return color_map

def pptk_subprocess(points, labels=None, label_dict=None, color_dict=None, interactive=False):
    # Generate "fake" labels by using the Z values for coloring
    if labels is None:
        labels = np.copy(points[:, 2])
        labels = (labels - np.min(labels)) / np.ptp(labels)

    # Generate the labels as RGB values if a colordict is given
    if label_dict is not None and color_dict is not None:
        colormap = generate_colormap_from_labels_colors(label_dict, color_dict)
        labels = colormap(labels.astype(np.int32))

    # Package the data into a temporary file to hand to the subprocess
    datafile = tempfile.NamedTemporaryFile(suffix='.npz', delete=False)
    np.savez(datafile.name, points=points, labels=labels, interactive=np.array([interactive]))

    # Start a process that calls this file
    commands = f'C:\ProgramData\Anaconda3\Scripts\\activate.bat && conda activate torch-pptk-py37 && python {__file__} {datafile.name}'
    subprocess.run(commands, shell=True)

    # If we were not interactive the subprocess wrote and image back into the datafile
    if not interactive:
        plot_image = mpimg.imread(datafile.name)
        datafile.close()
        os.remove(datafile.name)
        return plot_image

    return None

if __name__ == '__main__':
    # Dumbly figure out which argument is the datafile path
    datafile_path = None
    for a in sys.argv:
        if os.path.isfile(a) and '.py' not in a:
            datafile_path = a

    # Load and parse the points and labels from the file
    data = np.load(datafile_path)
    points = data['points']
    labels = data['labels']
    interactive = data['interactive'][0]

    if interactive:
        # Display this plot and wait for it to close from user input
        subprocess_interactive_lidar_pptk(points, labels)
    else:
        # Generate an image of the plot and get a NamedTempFile with it as an image
        tmpimg = subprocess_pptk_lidar_image(points, labels)

        # Copy the image from the returned file into the datafile
        shutil.copyfile(tmpimg.name, datafile_path)

        # Close and delete the temporary file
        tmpimg.close()
        os.remove(tmpimg.name)

相关问题