Python3 -m在Eclipse中运行配置

时间:2015-08-29 08:22:45

标签: python eclipse python-3.x pydev python-import

由于SO和其他地方的许多评论/问题/咆哮都会告诉您,使用相对导入的Python3包需要从中央__main__.py文件运行。在模块的情况下,说" modA"在一个包中,比如" packA",需要运行相对导入(例如因为运行测试包if __name__ == '__main__'),我们被告知运行而不是运行python3 -m modA.packA如果modA不包含sys.path()上方的目录,请从上面的目录modA开始。我可能不喜欢这种范式,但我可以解决它。

但是,当尝试从Eclipse / PyDev运行modA时,我无法弄清楚如何指定将使用-m标志正确执行模块的运行配置。有没有人想出如何设置一个能够正确执行此操作的运行配置?

参考文献:Relative imports for the billionth time; Relative import in Python 3 not working; Multilevel relative import

2 个答案:

答案 0 :(得分:2)

不幸的是,现在,它并没有在PyDev中自动运行-m,因此,我将提供3个选择在PyDev中使用相对导入,前面有dot(在PyDev版本中) 4.3.0):

  1. 不要使用相对导入,只使用__main__模块中的绝对导入。

  2. __main__创建一个单独的模块,它将对您要运行的模块执行绝对导入并改为运行该模块(如果您正在分发应用程序,则可能需要这样做人们在Python中启动代码的通常方法是将脚本作为参数传递给Python,而不是使用-m开关。

  3. 通过执行以下操作将-m module添加到运行配置中的vm参数:

    • 进行运行(由于相对导入而失败)
    • 右键单击编辑器>复制上下文合格的名称
    • 打开运行配置:Alt,R,N(即:工具栏>运行>运行配置)
    • 打开参数选项卡并添加'-m Ctrl + V'(添加-m和先前复制的模块名称)。
  4. 虽然这绝对不理想:你现在会收到一个带有文件名的参数(因为PyDev会一直传递它来运行文件),整个过程都很麻烦。

    作为一个说明,我希望尽快使用-m希望PyDev 4.4.0 )提供一种在PyDev中运行的方法......虽然这可能不是如果正在运行的文件不在PYTHONPATH下(例如:运行外部文件,它仍然必须支持没有-m的选项)。

答案 1 :(得分:0)

这是我在Fabio的第三个建议之后能够做到的。

创建一个名为/usr/local/bin/runPy3M的程序,具有全局读取/执行权限,使用以下代码:

#!/usr/local/bin/python3 -u
'''
Run submodules inside packages (with relative imports) given
a base path and a path (relative or absolute) to the submodule
inside the package.

Either specify the package root with -b, or setenv ECLIPSE_PROJECT_LOC.
'''

import argparse
import os
import re
import subprocess
import sys

def baseAndFileToModule(basePath, pyFile):
    '''
    Takes a base path referring to the root of a package
    and a (relative or absolute) path to a python submodule
    and returns a string of a module name to be called with
    python -m MODULE, if the current working directory is
    changed to basePath.

    Here the CWD is '/Users/cuthbert/git/t/server/tornadoHandlers/'.

    >>> baseAndFileToModule('/Users/cuthbert/git/t/', 'bankHandler.py')
    'server.tornadoHandlers.bankHandler'
    '''
    absPyFilePath = os.path.abspath(pyFile)
    absBasePath = None
    if basePath is not None:
        absBasePath = os.path.abspath(basePath)
        commonPrefix = os.path.commonprefix([absBasePath, absPyFilePath])
        uncommonPyFile = absPyFilePath[len(commonPrefix):]
    else:
        commonPrefix = ""
        uncommonPyFile = absPyFilePath 

    if commonPrefix not in sys.path:
        sys.path.append(commonPrefix)

    moduleize = uncommonPyFile.replace(os.path.sep, ".")
    moduleize = re.sub("\.py.?$", "", moduleize)
    moduleize = re.sub("^\.", "", moduleize)
    return moduleize    

def exitIfPyDevSetup():
    '''
    If PyDev is trying to see if this program is a valid
    Python Interpreter, it expects to function just like Python.
    This is a little module that does this if the last argument
    is 'interpreterInfo.py' and then exits.
    '''
    if 'interpreterInfo.py' in sys.argv[-1]:
        interarg = " ".join([sys.executable] + sys.argv[1:])
        subprocess.call(interarg.split())
        exit()
    return

exitIfPyDevSetup()

parser = argparse.ArgumentParser(description='Run a python file or files as a module.')
parser.add_argument('file', metavar='pyfile', type=str, nargs=1,
                   help='filename to run, with .py')
parser.add_argument('-b', '--basepath', type=str, default=None, metavar='path',
                   help='path to directory to consider the root above the package')
parser.add_argument('-u', action='store_true', help='unbuffered binary stdout and stderr (assumed)')
args = parser.parse_args()
pyFile = args.file[0]
basePath = args.basepath

if basePath is None and 'ECLIPSE_PROJECT_LOC' in os.environ:
    basePath = os.environ['ECLIPSE_PROJECT_LOC']

modName = baseAndFileToModule(basePath, pyFile)

allPath = ""
if basePath:
   allPath += "cd '" + basePath + "'; "

allPath += sys.executable
allPath += " -m " + modName 

subprocess.call(allPath, shell=True)  # maybe possible with runpy instead...

然后向PyDev添加一个新的解释器 - 称之为你想要的(例如,runPy3M)并将解释器指向/usr/local/bin/runPy3M。点击没关系。如果需要,然后将其上移到列表中。然后添加到解释器的环境,变量:ECLIPSE_PROJECT_LOC(这里名称很重要),值为${project_loc}

现在选择此解释器的包内的子模块将作为相对于子包的模块运行。

我希望baseAndFileToModule(basePath, pyFile)最终添加到runpy作为另一个运行选项,但现在可以使用。

编辑:不幸的是,在完成所有这些设置之后,似乎这个配置似乎阻止了Eclipse / PyDev识别内置组件,如“无”,“真”,“假”,“实例”等。所以不是完美的解决方案。