简体   繁体   English

Python外部项目脚本执行

[英]Python external project script execution

After many researches on the web, on many different topics, I wasn't able to find the solution answering my problem. 在网上进行了许多不同主题的研究之后,我找不到解决我问题的解决方案。

I am developing a tool (with graphic interface) allowing to process python scripts from different projects. 我正在开发一种工具(带有图形界面),该工具可以处理来自不同项目的python脚本。 To not have any problem of dependences, I ask the user to target the project directory as well as the script to process. 为了不存在任何依赖性问题,我要求用户将项目目录和要处理的脚本作为目标。

Thus to develop this tool I have in my IDE a project "benchmark_tool" which is the project integrating the GUI, and the project "test_project" which groups various testing scripts. 因此,为了开发此工具,我在我的IDE中有一个项目“ benchmark_tool”(该项目集成了GUI),还有一个项目“ test_project”(该项目对各种测试脚本进行了分组)。 Obviously, the final goal is the tool to be compiled and thus that the project "benchmark_tool" disappears from IDE. 显然,最终目标是要编译的工具,因此项目“ benchmark_tool”将从IDE中消失。

Here is the IDE architecture: 这是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

How it works: The main.py shall call test_script.py. 工作原理:main.py应调用test_script.py。 test_script.py calls imports.py at the first beggining of the script. 在脚本的第一次开始时,test_script.py调用imports.py。

UPDATE UPDATE

I tried some modifications in my main code: 我在主代码中尝试了一些修改:

import sys
import subprocess

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

I got this error 我得到这个错误

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

Note It works with subprocess.Popen(['python','D:/project/python/test_project/module1/test_script.py]) 注意它与subprocess.Popen(['python','D:/project/python/test_project/module1/test_script.py])

What's the main difference between both methods ? 两种方法的主要区别是什么? I'll also have to pass arguments to test_scripts.py, which one is the best to use to communicate with a python script (input and output datas are exchanged) ? 我还必须将参数传递给test_scripts.py,哪一种是与python脚本进行通信(交换输入和输出数据)的最佳方式?

Thanks by advance 预先感谢

To run an "external project script", install it eg: pip install project (run it in a virtualenv if you'd like) and then run the script as you would with any other executable: 要运行“外部项目脚本”,请安装它,例如: pip install project (如果需要,在virtualenv中运行它),然后像使用其他可执行文件一样运行脚本:

#!/usr/bin/env python
import subprocess

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

If you don't want to install the project and it has no dependencies (or you assume they are already installed) then to run a script from a given path as a subprocess (assuming there is module1/__init__.py file): 如果您不想安装项目并且它没有依赖项(或者假设它们已经安装),则可以从给定路径运行脚本作为子module1/__init__.py (假设存在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')

Using -m to run the script, avoids many import issues . 使用-m运行脚本,避免了许多导入问题

The above assumes that test_project is not a Python package (no test_project/__init__.py ). 上面假设test_project不是Python包(没有test_project/__init__.py )。 If test_project is itself a Python package then include it in the module name and start from the parent directory instead: 如果test_project本身是Python软件包,则将其包含在模块名称中,并从父目录开始:

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

You could pass the path to test_project directory as a command-line parameter ( sys.argv ) or read it from a config file ( configparser , json ). 您可以将路径作为命令行参数( sys.argv )传递到test_project目录,或从配置文件( configparserjson )中读取它。 Avoid calculating it relative to the installation path of your parent script (if you have to then use pkgutil , setuptools' pkg_resources , to get the data). 避免相对于父脚本的安装路径进行计算(如果必须使用pkgutil和setuptools的pkg_resources获取数据)。 To find a place to store user data, you could use appdirs Python package . 要找到存储用户数据的位置,可以使用appdirs Python package

There are 3 problems I see that you have to fix: 我认为您必须解决3个问题:

  1. In order to import from module2, you need to turn that directory into a package by placing an empty *__init__.py file in it 为了从module2导入,您需要通过在其中放置一个空的*__init__.py文件来将该目录转换为一个包。
  2. When executing test_script.py , you need the full path to the file, not just file name 执行test_script.py ,您需要文件的完整路径,而不仅仅是文件名
  3. Fixing up sys.path only work for your script. 修复sys.path仅适用于您的脚本。 If you want to propagate that to test_script.py , set the PYTHONPATH environment variable 如果要将其传播到test_script.py ,请设置PYTHONPATH环境变量

Therefore, my solution is: 因此,我的解决方案是:

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))

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

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