Python外部项目脚本执行

时间:2016-06-13 09:49:55

标签: python import path subprocess sys

经过对网络的许多研究,在许多不同的主题上,我无法找到解决问题的解决方案。

我正在开发一个工具(带图形界面),允许处理来自不同项目的python脚本。 为了没有任何依赖问题,我要求用户定位项目目录以及要处理的脚本。

因此,为了开发这个工具,我在我的IDE中有一个项目" benchmark_tool"这是集成GUI和项目的项目" test_project"其中包含各种测试脚本。显然,最终目标是要编译的工具,因此项目" benchmark_tool"从IDE中消失。

以下是IDE架构:

benchmark_tool (python project)
    __init__.py
    main.py

test_project (python project)
    __init__.py
    module1
        __init__.py
        test_script.py
    module2
        __init__.py
        imports.py

工作原理:main.py应调用test_script.py。 test_script.py在脚本的第一个初始化时调用imports.py。

更新

我在主代码中尝试了一些修改:

import sys
import subprocess

subprocess.check_call([sys.executable, '-m', 'test_project.module1.test_script'], cwd='D:/project/python')

我收到了这个错误

Traceback(most recent call last):
    File "C:/Python31/lib/runpy.py", line 110, in run module as main
        mod_name, loader, code, fname = _get_module_detail(mod_name)
    File "C:/Python31/lib/runpy.py", line 91, in get module details
        code = loader.get_code(mod_name)
    File "C:/Python31/lib/pkgutil.py", line 272, in get code
        self.code = compile(source, self.filename, 'exec')
    File "D:/project/python/test_project/module1/test_script.py", line 474


SyntaxError: invalid syntax
Traceback (most recent call last):
    File "D:/other_project/benchmark_tool/main.py", line 187, in read
        subprocess.check_call([sys.executable, '-m', 'module1.test_script.py'], cwd='D:/project/python/test_project')
    File "C:/Python31/lib/subprocess.py", line 446, in check call
        raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['C:/Python31/python.exe', '-m', 'module1.test_script.py']' returned non-zero exit status 1

注意 它适用于subprocess.Popen(['python','D:/project/python/test_project/module1/test_script.py])

两种方法的主要区别是什么?我还必须将参数传递给test_scripts.py,哪一个最适合用来与python脚本通信(输入和输出数据是否被交换)?

先谢谢

2 个答案:

答案 0 :(得分:0)

要运行“外部项目脚本”,请安装它,例如:pip install project(如果您愿意,可以在virtualenv中运行它),然后像运行任何其他可执行文件一样运行脚本:

#!/usr/bin/env python
import subprocess

subprocess.check_call(['executable', 'arg 1', '2'])

如果您不想安装项目并且它没有依赖项(或者您假设它们已经安装),那么从给定路径作为子进程运行脚本(假设有module1/__init__.py文件) :

#!/usr/bin/env python
import subprocess
import sys

subprocess.check_call([sys.executable, '-m', 'module1.test_script'], 
                      cwd='/abs/path/to/test_project')

使用-m运行脚本,避免使用many import issues

以上假设test_project不是Python包(无test_project/__init__.py)。如果test_project本身就是一个Python包,那么将它包含在模块名称中,然后从父目录开始:

subprocess.check_call([sys.executable, '-m', 'test_project.module1.test_script'], 
                      cwd='/abs/path/to')

您可以将路径作为命令行参数(test_project)传递到sys.argv目录,或者从配置文件(configparserjson)中读取它。避免相对于父脚本的安装路径计算它(如果必须使用pkgutil,setuptools'pkg_resources来获取数据)。要查找存储用户数据的位置,您可以使用appdirs Python package

答案 1 :(得分:0)

我发现有3个问题需要修复:

  1. 要从module2导入,您需要通过在其中放置一个空的*__init__.py文件将该目录转换为包
  2. 执行test_script.py时,您需要文件的完整路径,而不仅仅是文件名
  3. 修复sys.path只适用于您的脚本。如果要将其传播到test_script.py,请设置PYTHONPATH环境变量
  4. 因此,我的解决方案是:

    import os
    import sys
    import subprocess
    
    # Here is one way to determine test_project
    # You might want to do it differently
    script_dir = os.path.abspath(os.path.dirname(__file__))
    test_project = os.path.normpath(os.path.join(script_dir, '..', 'test_project'))
    
    python_path = '{}:{}'.format(os.environ.get('PYTHONPATH', ''), test_project)
    python_path = python_path.lstrip(':')  # In case PYTHONPATH was not set
    
    # Need to determine the full path to the script
    script = os.path.join(test_project, 'module1', 'test_script.py')
    proc = subprocess.Popen(['python', script], env=dict(PYTHONPATH=python_path))