任务计划程序中的批处理文件不是 运行 python 脚本

Batch file not running python script in task scheduler

我有一个 scraping python 脚本和一个批处理文件,当我从 CMD 运行 时,它可以完美地工作,但是当我尝试 运行它从任务计划程序没有任何反应。

我知道有很多关于同一问题的问题,但我已经尝试了所有建议的答案,但似乎没有一个有效。

不知道这是否相关,但脚本会打开 Firefox 并抓取一些网站。

已尝试为我正在使用的文件夹和文件添加完全权限。 此外,已尝试在任务计划程序中设置“运行 用户是否登录”、“运行 具有最高权限”、“开始于(可选):add/bactch/file/path”和等等

批处理文件:

py "C:\python_test\myscript.py"

它应该 运行 打开 Firefox 并抓取一些网站的 python 脚本,获取它们的链接并将它们保存在 csv 文件中

这里是myscript.py:

import datetime
import time
import csv
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
import os

file_path = r"C:\General\{0:%Y%m%d}\results{0:%Y%m%d%H%M%S}.csv".format(datetime.datetime.now())
directory = os.path.dirname(file_path)

try:
    os.stat(directory)
except:
    os.mkdir(directory)

from bs4 import BeautifulSoup
 
 
def init_driver():
    caps = DesiredCapabilities.FIREFOX
    caps['marionette'] = True
    driver = webdriver.Firefox(capabilities=caps)
    driver.wait = WebDriverWait(driver, 15)
    return driver
 

xpath = {
    'english': '//*[@id="xxx"]',
    'soort': '//*[@id="xxx"]/option[text()=\'|- Announcement of change in denominator or in thresholds\']',
    'start': '//*[@id="xxx"]',
    'end': '//*[@id="xxx"]',
    'submit': '//*[@id="xxx"]',
    'pub_sort': '//*[@id="xxx"]',
}
 
if __name__ == "__main__":

    driver = init_driver()
    try:
        driver.get("http://SOMEWEBSITE") 
        driver.find_element_by_css_selector('[id$=hplEnglish]').click()
    except Exception:
        DoNothing = ""

    
    time.sleep(2)
    driver.find_element_by_css_selector('[id$=hplEnglish]').click()
    time.sleep(3)
    #alert_obj = driver.switch_to.alert
    #alert_obj.dismiss()
    #driver.find_element_by_xpath(xpath['english']).click()
    today = datetime.datetime.now()
    driver.wait.until(EC.element_to_be_clickable((By.XPATH, xpath['soort']))).click()
    driver.find_element_by_xpath(xpath['start']).send_keys((today-datetime.timedelta(weeks=1)).strftime('%d/%m/%Y'))
    driver.find_element_by_xpath(xpath['end']).send_keys(today.strftime('%d/%m/%Y'))
    driver.find_element_by_xpath(xpath['submit']).click()
    for i in range(2):
        driver.wait.until(EC.element_to_be_clickable((By.XPATH, xpath['pub_sort']))).click()
    time.sleep(5)
    html = driver.page_source
    driver.quit()
    
    results = BeautifulSoup(html, 'html.parser').find('div', { 'id': 'SearchResults'}).table
    res = [['issuer', 'type', 'date']]
    for x in results.find_all('tr')[1:]:
        # print(x.text.strip())
        try:
            a, b, c = [i.text.strip() for i in x.find_all('td', class_='resultItemTop')[:3]]
            res.append([a,b,c])
        except ValueError:
            continue

        
    with open(file_path, 'w', newline='') as result:
        writer = csv.writer(result, delimiter=',')
        writer.writerows(res)
        print('finished')

简介

建议先阅读

问题 1:当前目录

这里的第一个问题很可能是 运行 批处理文件中的当前目录。

Windows 将批处理文件的目录设置为双击批处理文件时的当前目录,但批处理文件路径是以 \computername\share\.

开头的 UNC 路径

计划任务的当前目录默认为%SystemRoot%\System32,即Windows系统目录,当然是特别防止修改的。许多批处理文件期望当前目录是批处理文件的目录而不是任何其他目录。

解决方案 1:在计划任务的属性中定义 开始于 目录。

  • 启动 Windows 任务计划程序
  • 导航到任务并双击它以打开任务的属性
  • Select 选项卡 操作 并单击按钮 编辑
  • 开始于(可选)。在此处输入执行的批处理文件的路径。
  • 在按钮上单击两次 确定 以在属性中保存此重要修改。

解决方案 2:使用 CD.

使批处理文件目录成为当前目录

在批处理文件中,通常在第一行之后插入 @echo off 行:

cd /D "%~dp0"

此命令行将当前目录从默认 %SystemRoot%\System32 更改为批处理文件的目录,前提是批处理文件不是使用 UNC 路径启动的。

打开命令提示符 window 和 运行 cd /? 以获得有关命令 CD 和选项 /D 的帮助。

解决方案 3:使用 PUSHD.

使批处理文件目录成为当前目录

如果批处理文件存储在使用 UNC 路径访问的网络资源上,当然计划任务配置为 运行 具有读取内容权限的凭据(用户帐户和密码),则此解决方案是最好的网络资源上的批处理文件。

在批处理文件中,通常在第一行之后插入 @echo off 行:

setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0"

批处理文件还应包含在退出批处理文件处理这两行之前执行的最后两行:

popd
endlocal

打开命令提示符 window 和 运行 pushd /?popd /?setlocal /?endlocal /? 以获取有关这四个命令的帮助以及另请阅读 以获取有关这四个命令的更多详细信息。

解决方案 4:将所有内容编码为独立于当前目录。

第四种解决方案是编写批处理文件和Python脚本,以独立于执行批处理文件和Python脚本时当前目录是哪个目录。

此解决方案要求所有文件和目录都使用完整限定 file/folder 名称指定,这意味着完整路径 + file/folder 名称 + 文件扩展名。

完整的 file/folder 路径可以从执行时的已知路径派生,例如批处理文件的路径,可以在批处理文件中用 %~dp0 引用,并扩展为始终以路径字符串结尾带反斜杠,这意味着它可以与 file/folder 名称连接,而无需使用额外的反斜杠。

另请参阅有关 Windows Environment Variables 的维基百科文章。

问题 2:环境变量

计划任务通常使用 built-in 本地系统帐户执行。因此,为用于开发和测试批处理文件的用户帐户定义的所有环境变量要么根本没有定义,要么定义不同。

从 Windows 控制面板 打开项目 系统 高级系统设置 或按组合键 Win+Break 如果键盘有键 Break (通常作为替代功能需要另外按键 Fn ) 然后单击左侧的 高级系统设置 下一步。 System Properties 对话框打开时选择了 Advanced 选项卡,底部包含 Environment Variables... 按钮必须单击才能打开 环境变量 window.

有两个环境变量列表:...的用户变量系统变量system 变量是为所有帐户定义的,包括 built-in 本地系统帐户。 user 变量仅为显示的用户定义。

为当前用户定义的 user 变量很重要,这可能是当前用户双击执行的批处理文件有效,但在执行时不起作用的原因作为使用 built-in 系统帐户的计划任务。如果使用的脚本和可执行文件取决于 local PATH 中定义的特定文件夹路径 user PATH.

请查看 以获取有关 systemuserlocal[ 的更多信息=170=] PATH 和环境变量 PATHEXT 用于写入批处理文件只是 py 而不是具有完整限定文件名的 script/executable 文件。

所以用

肯定更好
"C:\Python27\python.exe" "C:\python_test\myscript.py"

而不是使用

py "C:\python_test\myscript.py"

这导致 cmd.exe 使用 local PATHEXTlocal[=170 搜索文件 py =] PATH 如果包含文件 py 的文件夹在 user PATH.

中定义,则可以归档的环境变量

我还没有安装 Python 所以不知道 py 到底是什么。它可以是文件名为 py.cmdpy.bat 的批处理文件,在这种情况下,如果批处理文件在命令后包含其他命令行,则必须使用命令 CALL符合 py 并且可能取决于 user 环境变量。它可以是Python安装文件夹中的符号link到python.exe。我不知道。

问题 3:网络资源

许多计划任务通过网络访问文件、文件夹或数据。在这种情况下,必须将计划任务配置为 运行,并使用具有访问网络资源上的文件、文件夹或数据所需权限的凭据(用户帐户和密码)。在这种情况下,使用 built-in 本地系统帐户几乎从来不是 运行 计划任务的正确选择,因为本地系统帐户通常没有权限访问任何网络资源上的 read/write 数据.

结论

在我看来,编写一个作为计划任务执行的批处理文件是一个很好的做法,它尽可能独立于其他批处理文件和未在 Windows 任务调度程序执行的批处理文件中定义的环境变量本身。依赖于其他脚本文件和在主脚本之外定义的变量的设计迟早会导致(有时是几年后)意外的执行问题。

编写脚本作为计划任务执行的程序员应该非常了解脚本和调用的可执行文件依赖于哪些文件、库、环境变量和注册表keys/values才能正常工作。

一个批处理文件只包含一行来执行一个带有一些参数的应用程序是完全没有必要的,它只是一个不工作计划任务的潜在来源,因为 运行 的可执行文件及其参数可以在这种情况下也可以直接在定时任务的属性中设置。绝对不需要 运行 %SystemRoot%\System32\cmd.exe 和隐式选项 /C 来处理指定的批处理文件,该批处理文件只包含一个命令行来执行具有零个或多个参数的应用程序,因为 Windows 任务调度程序也可以直接 运行 应用程序及其参数。