如何在Windows中以服务的形式运行Python脚本?

我正在为一组共享存储在数据库中的各种相关对象的程序绘制体系结构草图。我希望其中一个程序充当服务,为这些对象上的操作提供更高级别的接口,而其他程序通过该服务访问对象。

我目前的目标是将Python和Django框架作为实现该服务的技术。我很确定我知道如何在Linux中守护Python程序。但是,系统应该支持Windows,这是一个可选的规格项。我几乎没有Windows编程经验,对Windows服务也没有任何经验。

是否有可能运行Python程序作为Windows服务(即自动运行,无需用户登录)?我不一定要实现这一部分,但我需要一个粗略的想法,它将如何做,以决定是否沿着这些线设计。

编辑:谢谢你到目前为止所有的回答,他们是相当全面的。我想知道更多的事情: Windows如何意识到我的服务?我可以使用本机Windows实用程序管理它吗? 在/etc/init.d中放置启动/停止脚本的等效内容是什么? < / >强

391564 次浏览

是的,你可以。我使用ActivePython附带的pythoncom库,或者可以通过pywin32 (Python for Windows扩展)安装。

这是一个简单服务的基本框架:

import win32serviceutil
import win32service
import win32event
import servicemanager
import socket




class AppServerSvc (win32serviceutil.ServiceFramework):
_svc_name_ = "TestService"
_svc_display_name_ = "Test Service"


def __init__(self,args):
win32serviceutil.ServiceFramework.__init__(self,args)
self.hWaitStop = win32event.CreateEvent(None,0,0,None)
socket.setdefaulttimeout(60)


def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)


def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_,''))
self.main()


def main(self):
pass


if __name__ == '__main__':
win32serviceutil.HandleCommandLine(AppServerSvc)

你的代码会在main()方法中运行——通常带有某种无限循环,该循环可能会被检查你在SvcStop方法中设置的标志所中断

实际上,可以将任何Windows可执行文件安装为服务。

方法一:使用rktools.exe中的instsrv和srvany

对于Windows Home Server或Windows Server 2003(也适用于WinXP), Windows Server 2003资源工具包工具附带了可以串联使用的实用程序,称为instsrv.exesrvany.exe。有关如何使用这些utils的详细信息,请参阅Microsoft KB文章KB137890

对于Windows Home Server,这些实用程序有一个很好的用户友好包装器,命名为“任何服务安装程序”。

方法二:使用ServiceInstaller for Windows NT

还有另一种替代方法,使用ServiceInstaller for Windows NT (download-able这里)和可用的Python指令。与名字相反,它也适用于Windows 2000和Windows XP。下面是一些关于如何将python脚本作为服务安装的说明。

安装Python脚本

运行ServiceInstaller创建一个新的 服务。(在本例中,它是 假设python安装在 c: \ python25) < / p >

Service Name  : PythonTest
Display Name : PythonTest
Startup : Manual (or whatever you like)
Dependencies : (Leave blank or fill to fit your needs)
Executable : c:\python25\python.exe
Arguments : c:\path_to_your_python_script\test.py
Working Directory : c:\path_to_your_python_script

安装完成后,打开Control 面板的服务小程序,选择和

.启动PythonTest服务

在我最初的回答之后,我注意到SO上已经贴出了相关的Q&A。参见:

是否可以将Python脚本作为服务运行(Windows)?如何?< / >

如何让Windows知道我用Python编写的服务?< / >

虽然我在几周前对所选的答案进行了投票,但与此同时,我在这个话题上挣扎了很多。感觉使用特殊的Python安装并使用特殊的模块将脚本作为服务运行是一种错误的方式。可移植性如何?

我偶然发现了奇妙的非吸吮服务经理,它使处理Windows服务变得非常简单和理智。我想既然我可以将选项传递给已安装的服务,那么我也可以选择我的Python可执行文件并将脚本作为一个选项传递。

我还没有尝试过这个解决方案,但我会马上尝试,并在此过程中更新这篇文章。我也对在Windows上使用virtualenvs感兴趣,所以我可能迟早会想出一个教程,并链接到这里。

最简单的方法是使用本机命令sc.exe:

sc create PythonApp binPath= "C:\Python34\Python.exe --C:\tmp\pythonscript.py"

引用:

  1. https://technet.microsoft.com/en-us/library/cc990289(v=ws.11).aspx
  2. 当使用sc.exe创建服务时,如何传递上下文参数?< / >

pysc: Python中的服务控制管理器

作为服务摘自pythonhosted.org运行的示例脚本:

from xmlrpc.server import SimpleXMLRPCServer


from pysc import event_stop




class TestServer:


def echo(self, msg):
return msg




if __name__ == '__main__':
server = SimpleXMLRPCServer(('127.0.0.1', 9001))


@event_stop
def stop():
server.server_close()


server.register_instance(TestServer())
server.serve_forever()

创建并启动服务

import os
import sys
from xmlrpc.client import ServerProxy


import pysc




if __name__ == '__main__':
service_name = 'test_xmlrpc_server'
script_path = os.path.join(
os.path.dirname(__file__), 'xmlrpc_server.py'
)
pysc.create(
service_name=service_name,
cmd=[sys.executable, script_path]
)
pysc.start(service_name)


client = ServerProxy('http://127.0.0.1:9001')
print(client.echo('test scm'))

停止和删除服务

import pysc


service_name = 'test_xmlrpc_server'


pysc.stop(service_name)
pysc.delete(service_name)
pip install pysc

一步一步地解释如何使它工作:

1-首先根据上面提到的基本框架创建一个python文件。并将其保存到一个路径,例如:"c:\PythonFiles\AppServerSvc.py"

import win32serviceutil
import win32service
import win32event
import servicemanager
import socket




class AppServerSvc (win32serviceutil.ServiceFramework):
_svc_name_ = "TestService"
_svc_display_name_ = "Test Service"




def __init__(self,args):
win32serviceutil.ServiceFramework.__init__(self,args)
self.hWaitStop = win32event.CreateEvent(None,0,0,None)
socket.setdefaulttimeout(60)


def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)


def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_,''))
self.main()


def main(self):
# Your business logic or call to any class should be here
# this time it creates a text.txt and writes Test Service in a daily manner
f = open('C:\\test.txt', 'a')
rc = None
while rc != win32event.WAIT_OBJECT_0:
f.write('Test Service  \n')
f.flush()
# block for 24*60*60 seconds and wait for a stop event
# it is used for a one-day loop
rc = win32event.WaitForSingleObject(self.hWaitStop, 24 * 60 * 60 * 1000)
f.write('shut down \n')
f.close()


if __name__ == '__main__':
win32serviceutil.HandleCommandLine(AppServerSvc)

在这一步,我们应该注册我们的服务。

运行命令提示符管理员并输入as:

sc create TestService binpath= "C:\Python36\Python.exe C:\ PythonFiles\AppServerSvc.py" DisplayName= "TestService" start= auto

binpath的第一个参数是python.exe的路径

binpath的第二个参数是我们已经创建的python文件的路径

不要忘记在每个“”符号后面都应该加一个空格。

如果一切正常,你应该能看到

[SC] CreateService SUCCESS . [SC

现在你的python服务已经被安装为windows服务了。你可以在服务管理器和注册表中看到它:

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ \ TestService服务

3-好了。您可以在服务管理器上启动服务。

您可以执行提供此服务框架的每个python文件。

最简单的方法是使用:NSSM -非吸吮服务管理器。只需下载并解压缩到您选择的位置。它是一个自包含的实用程序,大约300KB(比为此目的安装整个pywin32套件少得多),并且没有“安装”。是必要的。zip包含一个64位版本和一个32位版本的实用程序。两者都应该在当前系统上运行良好(您可以使用32位版本来管理64位系统上的服务)。

GUI的方法

1 -将python程序作为服务安装。以管理员身份打开Win提示符

c:\>nssm.exe install WinService

2 -在NSSM的GUI控制台:

路径:C: \ Python27 \ Python27.exe

启动目录:C:\Python27

参数:c: \ WinService.py

3 -在services.msc上检查已创建的服务

脚本方法(没有GUI)

如果您的服务应该是自动化的、非交互式过程的一部分,例如批处理或安装程序脚本,那么这是非常方便的。假设这些命令是使用管理权限执行的。

为了方便起见,这里的命令被简单地称为nssm.exe。然而,在脚本中更明确地引用它的完整路径c:\path\to\nssm.exe是明智的,因为它是一个自包含的可执行文件,可能位于系统不知道的私有路径中。

1. 安装服务

您必须为服务指定一个名称,正确的Python可执行文件的路径,以及脚本的路径:

nssm.exe install ProjectService "c:\path\to\python.exe" "c:\path\to\project\app\main.py"

更明确:

nssm.exe install ProjectService
nssm.exe set ProjectService Application "c:\path\to\python.exe"
nssm.exe set ProjectService AppParameters "c:\path\to\project\app\main.py"

或者,你可能希望你的Python应用程序作为一个Python模块启动。一个简单的方法是告诉nssm它需要更改到正确的起始目录,就像你自己从命令shell启动时所做的那样:

nssm.exe install ProjectService "c:\path\to\python.exe" "-m app.main"
nssm.exe set ProjectService AppDirectory "c:\path\to\project"

这种方法适用于虚拟环境和自包含(嵌入式)的Python安装。只需确保在这些环境中使用常规方法正确解决了任何路径问题。nssm有一种方法可以在需要时设置环境变量(例如PYTHONPATH),还可以启动批处理脚本。

2. 启动服务

nssm.exe start ProjectService

3.停止服务

nssm.exe stop ProjectService

4. 删除服务,指定confirm参数来跳过交互确认。

nssm.exe remove ProjectService confirm

我开始使用pywin32作为服务托管。

一切都很好,但我遇到了一个问题,即服务无法在系统启动时的30秒内启动(Windows的默认超时)。这对我来说至关重要,因为Windows启动是在一台物理机上托管的多个虚拟机上同时进行的,IO负载非常大。 错误消息是:

Error 1053: The service did not respond to the start or control request in a timely fashion.

Error 7009: Timeout (30000 milliseconds) waiting for the <ServiceName> service to connect.

我与pywin进行了很多斗争,但最终使用了NSSM,因为它被提议在这个答案中。移居到那里很容易。

使用win32serviceutil可以接受的答案,但它很复杂,使调试和更改更加困难。它是< em >到< / em >更容易使用NSSM (非吸吮服务经理)。你编写并轻松调试一个普通的python程序,当它最终工作时,你使用NSSM在不到一分钟的时间内将其安装为服务:

在提升的(管理)命令提示符中运行nssm.exe install NameOfYourService并填写以下选项:

  • 路径:(python.exe的路径,例如C:\Python27\Python.exe)
  • 参数:(python脚本的路径,例如c:\path\to\program.py)

顺便说一下,如果您的程序打印了想要保存在日志文件中的有用消息,那么NSSM也可以为您处理这个问题。

< a href = " https://nssm。Cc /download" rel="nofollow noreferrer">nssm in python3 +

(我用pyinstaller将我的.py文件转换为.exe)

nssm: < p > 如前所述

  • 运行nssm install {ServiceName}
  • < p > 在NSSM的控制台:

    路径:< em >路径\ \你\ program.exe < / em >

    启动目录:路径\到\your\ #与路径相同,但没有你的program.exe

    参数:空 < / p >

如果您不想将项目转换为.exe

  • python \{\{your python.py file name}}创建一个.bat文件
  • 并将路径设置为。bat文件

使用循环或子线程的完整pywin32示例

在断断续续地研究了几天之后,这里是我希望找到的答案,使用pywin32来保持它的良好和自包含。

这是一个基于循环和基于线程的解决方案的完整工作代码。 它可以在python 2和3上运行,尽管我只在2.7和Win7上测试了最新版本。循环应该适用于轮询代码,而tread应该适用于更类似于服务器的代码。它似乎可以很好地与女服务员 wsgi服务器一起工作,因为它没有标准的方法来优雅地关闭

我还想指出,似乎有大量的例子,像,几乎是有用的,但在现实中误导,因为他们盲目地剪切和粘贴其他的例子。我可能是错的。但如果你从不等待,为什么要创建一个事件呢?

也就是说,我仍然觉得我在这里有点不稳定,特别是关于线程版本的退出有多干净,但至少我相信这里没有误导

要运行,只需将代码复制到文件中并按照说明操作即可。

更新:

使用一个简单标志来终止线程。重要的一点是“线程完成”;打印。
有关从不合作的服务器线程退出的更详细的例子,请参阅我的发布关于女招待wsgi服务器的文章.

# uncomment mainthread() or mainloop() call below
# run without parameters to see HandleCommandLine options
# install service with "install" and remove with "remove"
# run with "debug" to see print statements
# with "start" and "stop" watch for files to appear
# check Windows EventViever for log messages


import socket
import sys
import threading
import time
from random import randint
from os import path


import servicemanager
import win32event
import win32service
import win32serviceutil
# see http://timgolden.me.uk/pywin32-docs/contents.html for details




def dummytask_once(msg='once'):
fn = path.join(path.dirname(__file__),
'%s_%s.txt' % (msg, randint(1, 10000)))
with open(fn, 'w') as fh:
print(fn)
fh.write('')




def dummytask_loop():
global do_run
while do_run:
dummytask_once(msg='loop')
time.sleep(3)




class MyThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)


def run(self):
global do_run
do_run = True
print('thread start\n')
dummytask_loop()
print('thread done\n')


def exit(self):
global do_run
do_run = False




class SMWinservice(win32serviceutil.ServiceFramework):
_svc_name_ = 'PyWinSvc'
_svc_display_name_ = 'Python Windows Service'
_svc_description_ = 'An example of a windows service in Python'


@classmethod
def parse_command_line(cls):
win32serviceutil.HandleCommandLine(cls)


def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.stopEvt = win32event.CreateEvent(None, 0, 0, None)  # create generic event
socket.setdefaulttimeout(60)


def SvcStop(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STOPPED,
(self._svc_name_, ''))
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.stopEvt)  # raise event


def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
# UNCOMMENT ONE OF THESE
# self.mainthread()
# self.mainloop()


# Wait for stopEvt indefinitely after starting thread.
def mainthread(self):
print('main start')
self.server = MyThread()
self.server.start()
print('wait for win32event')
win32event.WaitForSingleObject(self.stopEvt, win32event.INFINITE)
self.server.exit()
print('wait for thread')
self.server.join()
print('main done')


# Wait for stopEvt event in loop.
def mainloop(self):
print('loop start')
rc = None
while rc != win32event.WAIT_OBJECT_0:
dummytask_once()
rc = win32event.WaitForSingleObject(self.stopEvt, 3000)
print('loop done')




if __name__ == '__main__':
SMWinservice.parse_command_line()

https://www.chrisumbel.com/article/windows_services_in_python

  1. 跟踪PySvc.py

  2. 更改DLL文件夹

我知道这很旧了,但我一直都困在这上面。对我来说,这个特定的问题是通过复制这个文件pywintypes36.dll解决的

Python36\Lib\site-packages\pywin32_system32

到> Python36\Lib\site-packages\win32

setx /M PATH "%PATH%;C:\Users\user\AppData\Local\Programs\Python\Python38-32;C:\Users\user\AppData\Local\Programs\Python\Python38-32\Scripts;C:\Users\user\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\pywin32_system32;C:\Users\user\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\win32
  1. 将路径更改为python文件夹

cd C:\Users\user\AppData\Local\Programs\Python\Python38-32

  1. NET START PySvc
  2. NET STOP PySvc
这个答案是从StackOverflow上的几个来源抄袭来的——上面大部分都是,但我忘记了其他的——对不起。它很简单,脚本按“原样”运行。对于发布,您测试脚本,然后将其复制到服务器并停止/启动相关的服务。它应该适用于所有脚本语言(Python, Perl, node.js),加上批处理脚本,如GitBash, PowerShell,甚至旧的DOS bat脚本。 pyGlue是位于Windows服务和你的脚本之间的胶水
'''
A script to create a Windows Service, which, when started, will run an executable with the specified parameters.
Optionally, you can also specify a startup directory


To use this script you MUST define (in class Service)
1. A name for your service (short - preferably no spaces)
2. A display name for your service (the name visibile in Windows Services)
3. A description for your service (long details visible when you inspect the service in Windows Services)
4. The full path of the executable (usually C:/Python38/python.exe or C:WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe
5. The script which Python or PowerShell will run(or specify None if your executable is standalone - in which case you don't need pyGlue)
6. The startup directory (or specify None)
7. Any parameters for your script (or for your executable if you have no script)


NOTE: This does not make a portable script.
The associated '_svc_name.exe' in the dist folder will only work if the executable,
(and any optional startup directory) actually exist in those locations on the target system


Usage: 'pyGlue.exe [options] install|update|remove|start [...]|stop|restart [...]|debug [...]'
Options for 'install' and 'update' commands only:
--username domain\\username : The Username the service is to run under
--password password : The password for the username
--startup [manual|auto|disabled|delayed] : How the service starts, default = manual
--interactive : Allow the service to interact with the desktop.
--perfmonini file: .ini file to use for registering performance monitor data
--perfmondll file: .dll file to use when querying the service for performance data, default = perfmondata.dll
Options for 'start' and 'stop' commands only:
--wait seconds: Wait for the service to actually start or stop.
If you specify --wait with the 'stop' option, the service and all dependent services will be stopped,
each waiting the specified period.
'''


# Import all the modules that make life easy
import servicemanager
import socket
import sys
import win32event
import win32service
import win32serviceutil
import win32evtlogutil
import os
from logging import Formatter, Handler
import logging
import subprocess




# Define the win32api class
class Service (win32serviceutil.ServiceFramework):
# The following variable are edited by the build.sh script
_svc_name_ = "TestService"
_svc_display_name_ = "Test Service"
_svc_description_ = "Test Running Python Scripts as a Service"
service_exe = 'c:/Python27/python.exe'
service_script = None
service_params = []
service_startDir = None


# Initialize the service
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
self.configure_logging()
socket.setdefaulttimeout(60)


# Configure logging to the WINDOWS Event logs
def configure_logging(self):
self.formatter = Formatter('%(message)s')
self.handler = logHandler()
self.handler.setFormatter(self.formatter)
self.logger = logging.getLogger()
self.logger.addHandler(self.handler)
self.logger.setLevel(logging.INFO)


# Stop the service
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)


# Run the service
def SvcDoRun(self):
self.main()


# This is the service
def main(self):


# Log that we are starting
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))


# Fire off the real process that does the real work
logging.info('%s - about to call Popen() to run %s %s %s', self._svc_name_, self.service_exe, self.service_script, self.service_params)
self.process = subprocess.Popen([self.service_exe, self.service_script] + self.service_params, shell=False, cwd=self.service_startDir)
logging.info('%s - started process %d', self._svc_name_, self.process.pid)


# Wait until WINDOWS kills us - retrigger the wait for stop every 60 seconds
rc = None
while rc != win32event.WAIT_OBJECT_0:
rc = win32event.WaitForSingleObject(self.hWaitStop, (1 * 60 * 1000))


# Shut down the real process and exit
logging.info('%s - is terminating process %d', self._svc_name_, self.process.pid)
self.process.terminate()
logging.info('%s - is exiting', self._svc_name_)




class logHandler(Handler):
'''
Emit a log record to the WINDOWS Event log
'''


def emit(self, record):
servicemanager.LogInfoMsg(record.getMessage())




# The main code
if __name__ == '__main__':
'''
Create a Windows Service, which, when started, will run an executable with the specified parameters.
'''


# Check that configuration contains valid values just in case this service has accidentally
# been moved to a server where things are in different places
if not os.path.isfile(Service.service_exe):
print('Executable file({!s}) does not exist'.format(Service.service_exe), file=sys.stderr)
sys.exit(0)
if not os.access(Service.service_exe, os.X_OK):
print('Executable file({!s}) is not executable'.format(Service.service_exe), file=sys.stderr)
sys.exit(0)
# Check that any optional startup directory exists
if (Service.service_startDir is not None) and (not os.path.isdir(Service.service_startDir)):
print('Start up directory({!s}) does not exist'.format(Service.service_startDir), file=sys.stderr)
sys.exit(0)


if len(sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(Service)
servicemanager.StartServiceCtrlDispatcher()
else:
# install/update/remove/start/stop/restart or debug the service
# One of those command line options must be specified
win32serviceutil.HandleCommandLine(Service)

现在有一些编辑,你不希望你所有的服务都叫“pyGlue”。所以有一个脚本(build.sh)来插入比特并创建一个自定义的“pyGlue”和创建一个“。exe”。就是这个“。exe”被安装为Windows服务。安装后,您可以将其设置为自动运行。

#!/bin/sh
# This script build a Windows Service that will install/start/stop/remove a service that runs a script
# That is, executes Python to run a Python script, or PowerShell to run a PowerShell script, etc


if [ $# -lt 6 ]; then
echo "Usage: build.sh Name Display Description Executable Script StartupDir [Params]..."
exit 0
fi


name=$1
display=$2
desc=$3
exe=$4
script=$5
startDir=$6
shift; shift; shift; shift; shift; shift
params=
while [ $# -gt 0 ]; do
if [ "${params}" != "" ]; then
params="${params}, "
fi
params="${params}'$1'"
shift
done


cat pyGlue.py | sed -e "s/pyGlue/${name}/g" | \
sed -e "/_svc_name_ =/s?=.*?= '${name}'?" | \
sed -e "/_svc_display_name_ =/s?=.*?= '${display}'?" | \
sed -e "/_svc_description_ =/s?=.*?= '${desc}'?" | \
sed -e "/service_exe =/s?=.*?= '$exe'?" | \
sed -e "/service_script =/s?=.*?= '$script'?" | \
sed -e "/service_params =/s?=.*?= [${params}]?" | \
sed -e "/service_startDir =/s?=.*?= '${startDir}'?" > ${name}.py


cxfreeze ${name}.py --include-modules=win32timezone

安装-复制'.exe'服务器和脚本到指定的文件夹。以管理员身份运行“。exe”,并选择“install”。以管理员身份打开Windows服务,并启动服务。若要升级,只需复制新版本的脚本并停止/启动服务。

现在每个服务器都是不同的——不同的Python安装,不同的文件夹结构。我为每个服务器维护一个文件夹,其中包含pyGlue.py和build.sh的副本。我创建了一个'serverBuild.sh'脚本,用于重建该服务器上的所有服务。

# A script to build all the script based Services on this PC
sh build.sh AutoCode 'AutoCode Medical Documents' 'Autocode Medical Documents to SNOMED_CT and AIHW codes' C:/Python38/python.exe autocode.py C:/Users/russell/Documents/autocoding -S -T
这并没有回答最初的问题,但可能会帮助其他想在Windows启动时自动启动Python脚本的人: 相反,看看Windows任务计划程序,如果你只是想在启动后启动一个脚本,而不需要Windows服务的所有服务功能,它会更容易

创建一个新任务,选择“;在启动时”;作为触发器,“;启动程序”;C:\Python39\python.exe"将脚本的完整路径(" C:…\my_dir\xyz.py")作为参数(您可以使用"如果路径中包含空格)。 您还可以为“start in”选择脚本的路径(不包含.py文件,例如“C:…\my_dir"”);如果你在脚本中使用相对路径,例如用于日志记录