问题
我有一个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),所以文件不是首先创建的。)