Python subprocess.call在脚本位于一个目录但不在另一个目录中时起作用

时间:2016-09-02 14:57:09

标签: python windows visual-studio batch-file subprocess

问题

我有一个Python脚本,它一度调用一个子进程,等待它的执行,然后使用进程'写入文件的结果。

# call external algorithm and retrieve its results after completion
process_result = subprocess.call([executable, parameters]);
print(str(process_result));
results = retrieve_results(result_file_name);

executable包含要调用的文件的名称和路径,子文件夹中的* .bat脚本,parameters是传递给此脚本的参数列表。 * .bat本身设置一个路径变量,然后调用一个可执行文件,然后根据参数计算并保存结果。

这很好用。

然而。当我将所有涉及的文件复制到桌面上的目录(或者,其他任何地方)时,它就会崩溃。所有文件和完整的目录结构都是工作设置的精确副本。 Python脚本和* .bat中使用的所有路径都是相对的。我已将Windows设置为显示隐藏文件,但没有。

然而,当我运行复制的程序时,它会报告“语法错误”并且process_result为1而不是0.然后它会引发错误,因为result_file_name后面的文件不存在 - 它尚未创建,可执行文件尚未(完全)执行。

此设置应该适用于另一台计算机。如果我不能让它在同一台机器上的不同的文件夹中运行,我对这项努力没有太大的期望。尽管如此,我仍然完全失去了为什么以及如何发生这种情况。

涉及的文件

除了脚本本身,还有一个文件夹,其中包含在MATLAB中创建的第三方可执行文件和包含* .csv文件中的日志数据的文件夹。

.
├── my_script.py
├── estimation
|   ├── estimation.bat (setups Runtime and calls estimation.exe)
|   ├── estimation.exe (does the processing and produces/overwrites estimates.txt)
|   ├── estimates.txt (contains the results of the third-party processing)
|   ├── v901 (MATLAB stuff)
|   |   ├── ... 
├── test_inputs (files contain log lines that are processed in estimation.exe)
|   ├── 2016_04_01_04_07.csv 
|   ├── 2016_04_01_04_13.csv 
|   ├── ... (etc.)

由于我没有MATLAB,可执行文件自带有位于v901及其子目录中的MATLAB Runtime,并且必须使用首先设置Runtime的批处理脚本调用可执行文件,以便可执行文件可以使用它。这就是它的样子:

@echo off
:: prepare matlab runtime
set PATH=%~dp0\v901\runtime\win64;%PATH%
:: call estimation algorithm
estimation.exe %*

最小的例子

我将脚本缩减为仅与第三方算法的交互以创建最小的示例。两个文件夹(估计和test_inputs)都完全复制到一个新位置,以及Python脚本,保持文件树完好无损,如上所述。 此代码适用于原始文件夹,但不适用于任何其他文件夹。但是,我无法提供原始可执行文件,因为它是1)不是我的,2)需要近2 GB的v901文件夹。

import os
import subprocess
import time

# the folder to watch for new input files 
input_directory = "test_inputs";

# the file to run for processing
#executable_file = "third_party_program\\executable.bat";
estimation_executable = "estimation\\estimation.bat";

# debug line for the algorithm
estimation_debug_line = "null";

# parameters for the algorithm
estimation_parameters = "";

# file in which processing results are saved
result_file = "estimates.txt";



# function to print outputs after succesful processing
def print_processing_results (result_directory):

    try:

        processing_results = result_directory +"\\" + result_file;

        # open the executable's "log" file
        with open (processing_results) as results: 

            # print all lines in the log
            for line in results:                   
                print(line.strip());

    except IOError as ioe:
        print(ioe);


# function that calls the third-party algorithm
def call_function (input_file):

    # memorize current working directory (to change back to it later)
    working_directory = os.getcwd();

    # change current working directory to third party algorithm's directory
    # (necessary for the batch script to work in its folder)
    dirs = estimation_executable.split("\\");
    estimation_directory = "\\".join(dirs[0:len(dirs)-1]);
    os.chdir(estimation_directory);

    # build path to the input file
    input_path = "";
    if (os.path.isabs(input_directory)):
        input_path = input_directory + "\\" + input_file;
    else: 
        input_path = working_directory + "\\" + input_directory + "\\" + input_file;

    # build call strings
    executable = dirs[len(dirs)-1]; # name of the executable file to call
    parameters = input_path + "|" + str(estimation_debug_line) + "|" + estimation_parameters; # parameters for the executable

    try:

        print("now calling: " + str([executable, parameters]));

        # call third-party algorithm 
        process_result = subprocess.call([executable, parameters]);
        print("process_result = " + str(process_result));

        # change working directory back to the original
        os.chdir(working_directory);

        # print results of third-party processing
        print_processing_results(estimation_directory);

    except subprocess.CalledProcessError as cpe:
        print(cpe);




# test the whole thing ---- ------- ---- ------- ---- ------- ---- ------- 
try:

    # initialize latest file
    latest_file = "";

    while (True): # the program loop

        print("... looking for new files ...");

        # retrieve newest file in input directory since last update 
        # (files are sorted alphanumerically first)
        filebase = sorted(os.listdir(input_directory));
        latest_new_file = filebase[len(filebase)-1];
        if (latest_new_file > latest_file): 
            latest_file = latest_new_file;
        else:
            latest_new_file = "";

        # if there is a new latest file, process it
        # with the third-party algorithm
        if latest_new_file:
            call_function(latest_new_file);

        # wait before checking for the next new file
        time.sleep(30);

# upon exiting or force-quitting the script
except (KeyboardInterrupt, SystemExit):
    print("Script has been terminated.");

原始文件夹中的输出:

... looking for new files ...
now calling: ['estimation.bat', 'C:\\...(original folder)...\\test_inputs\\2016_04_01_04_07.csv|null|']
process_result = 0
results line 1
results line 2
(...)
... looking for new files ...
Script has been terminated.

另一个文件夹中的输出:

... looking for new files ...
now calling: ['estimation.bat', 'C:\\...(new folder)...\\test_inputs\\2016_04_01_04_07.csv|null|']
process_result = 1
[Errno 2] No such file or directory: 'estimation\\estimates.txt'
... looking for new files ...
Script has been terminated.

(当然,实际错误不是这里的问题,它只是因为可执行文件没有被执行(process_result = 1),所以文件不是首先创建的。)

0 个答案:

没有答案