Python3 -m 运行 Eclipse 中的配置
Python3 -m run configuration in Eclipse
2021 年更新:解决方案内置于 PyDev/Eclipse
有关详细信息,请参阅已接受的答案
下面的原始问题(和旧答案)
SO 和其他地方的许多 comments/questions/rants 会告诉您,使用相对导入的 Python3 包希望 运行 来自中央 __main__.py
文件。如果模块在包中说“modA”,说“packA”,使用相对导入需要是 运行(例如,因为测试包是 运行 if __name__ == '__main__'
),如果 sys.path()
不包含 modA
上面的目录,我们会被告知 运行 而不是 modA
上面的目录中的 运行 python3 -m modA.packA
。我可能不喜欢这种范式,但我可以解决它。
当尝试从 Eclipse/PyDev 运行 modA
时,我不知道如何指定 运行 配置来正确执行模块-m
标志。有没有人想出如何设置可以正确执行此操作的 运行 配置?
参考文献:Relative imports for the billionth time ; Relative import in Python 3 is not working ; Multilevel relative import
现在(自 PyDev 5.4.0 (2016-11-28))你可以去 Settings > PyDev > Run
和 select Launch modules with python -m mod.name
而不是 python filename.py
;)
参见:https://www.pydev.org/history_pydev.html
对于旧版本的 PyDev(旧答案)
不幸的是,现在,它在 PyDev 中不是自动的 运行 -m
,所以,我将提供 3 个在 PyDev 中工作的选择,相对导入前面有一个 dot
(在 PyDev 版本 4.3.0 中):
不要使用相对导入,只在 __main__
模块中使用绝对导入。
为 __main__
创建一个单独的模块,它将对您想要 运行 和 运行 的模块进行绝对导入(如果您'分发您的应用程序,无论如何这可能是需要的,因为人们在 Python 中启动您的代码的通常方式是将脚本作为参数传递给 Python 而不是使用 -m
开关)。
通过执行以下操作将 -m module
添加到 运行 配置中的 vm 参数:
- 制作运行(由于相对导入会失败)
- 右键单击编辑器 > 复制上下文限定名称
- 打开运行配置:Alt、R、N(即:工具栏>运行>运行配置)
- 打开参数选项卡并添加“-m Ctrl+V”(添加 -m 和您之前复制的模块名称)。
虽然这绝对不是理想的:你现在会收到一个带有文件名的参数(因为 PyDev 总是将它传递给 运行 文件)并且整个过程很麻烦。
请注意,我确实希望尽快提供一种使用 -m
在 PyDev 中制作 运行s 的方法(希望 PyDev 4.4.0)...虽然如果文件 运行 不在 PYTHONPATH 下这可能是不可能的(即:对于 运行 外部文件它仍然必须支持没有 [=13= 的选项]).
2021 年更新:不再需要此答案。有关详细信息,请参阅已接受的答案。
这是在 Fabio 的伟大建议之后我能够做到的。
创建一个名为 /usr/local/bin/runPy3M
的程序,具有世界 read/execute 权限,代码如下:
#!/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 识别诸如“None”、“True”、“False”、“ isinstnance," 等。所以不是一个完美的解决方案。
这里有一个有点讨厌的技巧可以解决这个问题。我正在使用 PyDev 9.2.0
将你的 venv 放在工作区中,比如在目录“venv”下。
刷新您的 eclipse 工作区并确保它使用此 venv(通过您的解释器设置)。
刷新后,转到 运行 配置并通过单击浏览按钮编辑“主模块”。
现在将出现 venv。
浏览到 venv/lib/python3.8/site-packages
在那里你会找到 pip 安装的模块源代码,你可以 select 你想要的模块 运行。
2021 年更新:解决方案内置于 PyDev/Eclipse
有关详细信息,请参阅已接受的答案
下面的原始问题(和旧答案)
SO 和其他地方的许多 comments/questions/rants 会告诉您,使用相对导入的 Python3 包希望 运行 来自中央 __main__.py
文件。如果模块在包中说“modA”,说“packA”,使用相对导入需要是 运行(例如,因为测试包是 运行 if __name__ == '__main__'
),如果 sys.path()
不包含 modA
上面的目录,我们会被告知 运行 而不是 modA
上面的目录中的 运行 python3 -m modA.packA
。我可能不喜欢这种范式,但我可以解决它。
当尝试从 Eclipse/PyDev 运行 modA
时,我不知道如何指定 运行 配置来正确执行模块-m
标志。有没有人想出如何设置可以正确执行此操作的 运行 配置?
参考文献:Relative imports for the billionth time ; Relative import in Python 3 is not working ; Multilevel relative import
现在(自 PyDev 5.4.0 (2016-11-28))你可以去 Settings > PyDev > Run
和 select Launch modules with python -m mod.name
而不是 python filename.py
;)
参见:https://www.pydev.org/history_pydev.html
对于旧版本的 PyDev(旧答案)
不幸的是,现在,它在 PyDev 中不是自动的 运行 -m
,所以,我将提供 3 个在 PyDev 中工作的选择,相对导入前面有一个 dot
(在 PyDev 版本 4.3.0 中):
不要使用相对导入,只在
__main__
模块中使用绝对导入。为
__main__
创建一个单独的模块,它将对您想要 运行 和 运行 的模块进行绝对导入(如果您'分发您的应用程序,无论如何这可能是需要的,因为人们在 Python 中启动您的代码的通常方式是将脚本作为参数传递给 Python 而不是使用-m
开关)。通过执行以下操作将
-m module
添加到 运行 配置中的 vm 参数:
- 制作运行(由于相对导入会失败)
- 右键单击编辑器 > 复制上下文限定名称
- 打开运行配置:Alt、R、N(即:工具栏>运行>运行配置)
- 打开参数选项卡并添加“-m Ctrl+V”(添加 -m 和您之前复制的模块名称)。
虽然这绝对不是理想的:你现在会收到一个带有文件名的参数(因为 PyDev 总是将它传递给 运行 文件)并且整个过程很麻烦。
请注意,我确实希望尽快提供一种使用 -m
在 PyDev 中制作 运行s 的方法(希望 PyDev 4.4.0)...虽然如果文件 运行 不在 PYTHONPATH 下这可能是不可能的(即:对于 运行 外部文件它仍然必须支持没有 [=13= 的选项]).
2021 年更新:不再需要此答案。有关详细信息,请参阅已接受的答案。
这是在 Fabio 的伟大建议之后我能够做到的。
创建一个名为 /usr/local/bin/runPy3M
的程序,具有世界 read/execute 权限,代码如下:
#!/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 识别诸如“None”、“True”、“False”、“ isinstnance," 等。所以不是一个完美的解决方案。
这里有一个有点讨厌的技巧可以解决这个问题。我正在使用 PyDev 9.2.0
将你的 venv 放在工作区中,比如在目录“venv”下。
刷新您的 eclipse 工作区并确保它使用此 venv(通过您的解释器设置)。
刷新后,转到 运行 配置并通过单击浏览按钮编辑“主模块”。 现在将出现 venv。
浏览到 venv/lib/python3.8/site-packages
在那里你会找到 pip 安装的模块源代码,你可以 select 你想要的模块 运行。