Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在windows上从Python3.x获取git标记_Python_Git_Powershell - Fatal编程技术网

在windows上从Python3.x获取git标记

在windows上从Python3.x获取git标记,python,git,powershell,Python,Git,Powershell,我尝试过,但无法在Windows10上用Python 3.8完成一项看似微不足道的任务。 在PowerShell(core)中,我用不到2分钟的时间编写: repo = "../micropython/git" return (&git --git-dir=$repo describe --tags $(git --git-dir=$repo rev-list --tags='v[0-9].[0-9]*' --max-count=1)) 结果是该分支所在的“v1.12”(或任何最新版本

我尝试过,但无法在Windows10上用Python 3.8完成一项看似微不足道的任务。 在PowerShell(core)中,我用不到2分钟的时间编写:

repo = "../micropython/git"
return (&git --git-dir=$repo describe --tags $(git --git-dir=$repo rev-list --tags='v[0-9].[0-9]*' --max-count=1))
结果是该分支所在的“v1.12”(或任何最新版本)

在花了太多时间在这个假定的oneliner上之后,使用python我根本无法得到任何结果

尝试:

# 1 feeding it the commandline as text 
cmd_str = "git --git-dir=../micropython/.git describe --tags $(git --git-dir=../micropython/.git rev-list --tags='v[0-9].[0-9]*' --max-count=1)"
subprocess.run( cmdstr , capture_output=True,shell=True)

#2 splitting the cmdline using shlex.split 

command_line = """
git describe --tags $(git rev-list --tags=\"v[0-9].[0-9]*\" --max-count=1)
"""
cmd = shlex.split(command_line)
x = subprocess.run( cmd, capture_output=True )
print(x)

# 3 using the 'gitpython' library
would not even import .... : see issue below

#4..20 
many variations of the above 

因此,作为一名开发人员,对我来说,最简单的方法似乎是从python到powershell(因为这是跨平台的),并获得依赖性

不过,我是在python而不是powershell中开始编写的,因为脚本是为python社区编写的(并且是一种学习体验),当然有一种方法可以以更类似于pylike的方式完成这项工作,甚至可能有点优雅

版本:

  • Microsoft Windows[版本10.0.19041.1]
  • git版本2.24.1.windows.2
  • Python 3.8.1
。。。当然有一种方法可以做到这一点,更像派尔式的,甚至有点优雅的方式

编码员眼中的优雅。您可能会发现使用多种Git包装中的一种更为优雅。然而,您的第一种方法相对简单,有很多优点。我们可以避免新的3.7版本
capture_output=True
,以防有人(cough me cough)将3.6作为他们方便的测试系统的基础版本,并允许使用shell,这是
$(…)
扩展所需的,这或多或少让我们第一次尝试。但是我们可以利用这样一个事实,即
--git dir
相当于在环境中设置
git_dir
,这意味着我们不必在命令字符串中执行两次:

import os, subprocess

env = os.environ.copy()
env["GIT_DIR"] = "../micropython/.git"
cmd = "git describe --tags $(git rev-list --tags='v[0-9].[0-9]*' --max-count=1)"
ret = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
    env=env, shell=True)
(当然,只要所有python都是3.7或更高版本,就可以使用
capture\u output=True
作为两个stdout/stderr的缩写)

请注意,我们必须保存结果。这就是为什么我们在这里有
ret=
来捕获结果。我们现在在
ret
中得到了结果:

>>> print(ret)
CompletedProcess(args="git describe --tags $(git rev-list --tags='v[0-9].[0-9]*' --max-count=1)", returncode=0, stdout=b'v2.24.0\n', stderr=b'')
请注意,
retcode
是零,也就是说,作为一个整体,这两个
stdout
stderr
字段是字节而不是字符串。要解决此问题,我们可以在之后解码结果:

>>> print(ret.stdout.decode('utf-8'))
v2.24.0

>>> 
(假设输出为UTF-8)或让
子流程为我们执行。现代(3.7或更高版本)的方法是设置
text=True
,但由于在这台特定的机器上我仍然坚持使用3.6,因此我使用了旧的方法:

ret = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
    env=env, shell=True, universal_newlines=True)
这将产生更有用的结果:

>>> print(ret)
CompletedProcess(args="git describe --tags $(git rev-list --tags='v[0-9].[0-9]*' --max-count=1)", returncode=0, stdout='v2.24.0\n', stderr='')
请注意,使用
shell=True
。也就是说,在Windows上,您可以得到“COMSPEC
环境变量”中的任何shell。使用默认的
shell=False
并分别调用每个组件可能更明智:

import os, shlex, subprocess

env = os.environ.copy()
env["GIT_DIR"] = "../micropython/.git"

cmd = shlex.split("git rev-list --tags='v[0-9].[0-9]*' --max-count=1")
ret = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
if ret.returncode == 0:
    # Note: I tested this w/o using universal_newlines=True and it
    # worked fine, although the notion of adding a list of bytes to
    # a list of strings seems a bit odd.  This might not work well on
    # Windows; consider adding `text=True` or `universal_newlines=True`
    # above (and again below).
    cmd = shlex.split("git describe --tags") + [ret.stdout.strip()]
    ret = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
此时,
ret
再次适合检查:如果
ret.returncode
为零,
ret.stdout
具有来自
git sdescribe
的字节字符串。根据需要为文本翻译添加适当的字节

>>> print(ret)
CompletedProcess(args=['git', 'describe', '--tags', b'da72936f544fec5a335e66432610e4cef4430991'], returncode=0, stdout=b'v2.24.0\n', stderr=b'')

如果
ret.returncode
不为零,则说明
git description
失败,或者先前的
git rev列表失败。您在
ret.args
中有失败的命令,它的状态在
ret.returncode
中,在
ret.stdout
中有任何stdout文本,在
ret.stderr

中有来自Git的任何错误消息Powershell是跨平台的?如果安装了,使用最简单的语法可能会更简单。为子shell运行一个子脚本,然后将结果拼接到主脚本中。是的,pwsh 6.x,也称为PowerShell Core,在许多不同的体系结构上运行。看,我同意你写的大部分内容;但是计算机说不:
CompletedProcess(args=“git description--tags$(git rev list--tags='v[0-9].[0-9]*'--max count=1)”,returncode=129,stdout=b'',stderr=b“error:option
tags'不带任何值”`你们的参考平台是什么?我在一台机器上运行git版本2.24,在另一台机器上运行2.20.1。Git早在2010年就获得了对commit中的
--tags=
的支持,在Git版本1.7.0.BTW中,看看您最初的问题陈述,如果我将其正确理解为“描述当前分支”,那么您的PowerShell代码就太复杂了。您得到的是一种在所选修订版上运行
git descripe
的方法,方法是枚举与所选全局模式匹配的标记中日期最高的提交。我相信,我让Python代码做了与shell命令相同的事情。