简体   繁体   English

在python exe中调用子流程脚本的最佳方法

[英]Best way to call subprocess scripts in a Python exe

I'm currently trying to make a cross-platform Python exe file that relies on calling other Python and R scripts. 我目前正在尝试制作一个依赖于调用其他Python和R脚本的跨平台Python exe文件。 One issue I was facing was that my exe file expected my script files to be in the root directory as opposed to the directory where my exe file is. 我面临的一个问题是我的exe文件期望我的脚本文件位于根目录中,而不是我的exe文件所在的目录中。 I've managed to fix this by doing the following 我已经通过执行以下操作来解决此问题

   if getattr(sys, 'frozen', False):
        PROJECT_ROOT = sys.executable
   else:
        PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))

   pwd = os.path.dirname(PROJECT_ROOT)

   # messagebox is for the tkinter based GUI

   messagebox.showinfo('Info', 'Please wait a moment')
   subprocess.call(['python', pwd + '/Customs.py'], shell = False)
   subprocess.call(['Rscript', pwd + '/r_script.R'], shell=False)
   subprocess.call(['python', pwd + '/by_month.py'], shell = False)
   messagebox.showinfo('Info', 'Processing completed)

I'm wondering if there is a cleaner/ more reliable way of doing this to decrease the potential of an error occurring that might break the software. 我想知道是否有一种更清洁/更可靠的方法来减少发生可能破坏软件的错误的可能性。

I should also mention that I've read something about turning the other scripts into an exe file first and I would like to hear your opinion on this. 我还应该提到,我已经阅读了一些有关将其他脚本首先转换为exe文件的内容,并且我想听听您对此的看法。

Thanks 谢谢

First I suggest you use a function that returns the current path of your file when it is running as a frozen script or running normally to make testing of your code easy. 首先,我建议您使用一个函数来将文件作为冻结脚本运行或正常运行时返回文件的当前路径,以使代码测试变得容易。

Second, if you want to bundle your script files you need to first bundle your files with executable as a DATA file . 其次,如果要捆绑脚本文件,则需要先将文件和可执行文件捆绑为DATA文件 Next prepare the path for that file when using them with the said function. 接下来,将其与所述功能结合使用时,为该文件准备路径。

def app_path():
    if getattr(sys, 'frozen', False):
        app_path = os.path.dirname(sys.executable)
    elif __file__:
        app_path = os.path.dirname(__file__)
    return app_path


def resource_path(relative_path):
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)


# messagebox is for the tkinter based GUI
messagebox.showinfo('Info', 'Please wait a moment')
subprocess.call(['python', resource_path('Customs.py')], shell=False)
subprocess.call(['Rscript', resource_path('r_script.R')], shell=False)
subprocess.call(['python', resource_path('by_month.py')], shell=False)

messagebox.showinfo('Info', 'Processing completed)

And your command to build your app would be something like this: 您构建应用程序的命令将如下所示:

pyinstaller -F --add-data "Customs.py;." --add-data "r_script.R;." --add-data "by_month.py;." myscript.py

When your app runs, the data files Customs.py , r_script.R , etc would be extracted to a temp folder and resource_path would return the exact path for each file. 当你的应用程序运行,数据文件Customs.pyr_script.R等将被抽取到一个临时文件夹和resource_path将返回的确切路径每个文件。 But remember that if you want to load some files from your current directory (Where the exe file located) you can use app_path function. 但是请记住,如果要从当前目录(exe文件所在的位置)加载某些文件,则可以使用app_path函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM