如何处理 dev 和 prod 之间的代码差异?
How to handle code differences between dev and prod?
这可能是一个很长的问题,所以提前致歉。
这是我的情况,希望你们能帮我走上正轨:
塞纳里奥:
我有 2 个主要文件,我们称它们为 app-prod.py 和 app-dev.py。
两个(程序?)文件都使用 Selenium 来抓取网站,一个是主站点(工作),另一个是开发站点(本地)。
app-prod.py 需要一些登录代码(用户名、密码和授权代码)并且它必须告诉 Selenium 单击仅在生产站点上的某些按钮。
app-dev.py 不需要身份验证或导航说明,因为站点不同。开发站点只是一些模仿生产站点但没有所有登录内容的 html table。
生产代码示例:
# app-prod.py
"""open browser to base url, login and get ready
logic to login and go to the right page goes here"""
base_url = config[env]["base_url"]
browser = Firefox()
browser.get(base_url)
print("Sleeping for 5 to let page load")
time.sleep(5)
# LOGIN SCRIPT
auth = input("Enter Auth Code: ")
username = "LETMEIN"
password = "P@55W@rD"
browser.find_element_by_xpath('//*[@id="username"]').send_keys(username)
browser.find_element_by_xpath('//*[@id="password_input"]').send_keys(password)
browser.find_element_by_xpath('//*[@id="secondary_password_input"]').send_keys(auth)
browser.find_element_by_xpath('//input[@name="Login"]').click()
print("Sleeping for 3 to let page load")
time.sleep(3)
# Click OK button on alert
browser.find_element_by_xpath('//input[@value="Continue"]')
class Table:
def __init__(self, vls, name, intro):
**********
开发代码示例:
# app-dev.py
"""open browser to base url, login and get ready
logic to login and go to the right page goes here"""
base_url = config[env]["base_url"]
browser = Firefox()
browser.get(base_url)
class Table:
def __init__(self, vls, name, intro):
**********
我的问题是跟踪 2 个不同的文件。如果我处理开发代码,那么我必须将所有更改添加到 prod 文件,同时确保不要弄乱登录代码部分。
我目前正在使用 VS Code 比较这两个文件,然后 copy/paste 从开发到生产的差异,这是可行的,但有点乏味。
我尝试将代码的登录部分模块化并导入它,但它抱怨“浏览器”未定义(因为 webdriver 正在 app-*.py 文件中初始化)。
我以为当你导入一个模块时,它会把“import_me.py”中的所有东西都放到“app-dev.py”中,这样模块中的任何代码都可以使用任何主应用程序文件中的导入,但它似乎不是那样工作的。
就好像 python 在自己的小部分中将模块作为独立文件运行,而不与主文件交互。
所以,我的下一个想法是看看是否有一种模板应用程序的方法-dev.py 所以我可以说:
here is some dev code blah blah blah.
env='DEV'
if env == 'DEV'
{{ include login code here that is imported from import_me.py}}
else:
pass
不过好像没有这种东西。
每次我想测试某些东西时,我都无法一直访问生产站点,而且除了比较和手动进行更改之外,似乎没有一种干净的方法来处理两个不同的文件。
我正在使用 configparser 来更改 urls 和文件路径,但我认为它不能处理代码块,至少我没有在任何地方的文档中看到它。
你们是如何解决此类问题的?我编程的时间不长,所以我可能错过了一个可以解决这个问题的包,但现在,我没有想法。
非常感谢您能给我的任何帮助,希望能让我成为更好的程序员!
如果你做到了这一步,谢谢!有一个虚拟 cookie :)
TL;DR:需要一种方法将文件 1 中的代码块包含到文件 2 的特定区域中,文件 1 共享文件 2 的所有导入,就好像它是在运行时在那里硬编码一样。
**** 编辑以获取更多信息 ****
我会在明天查看有关发布代码的信息,因为我现在面前没有它。
这是我在做什么:
设置 Selenium 以打开网页,登录(在产品代码中),然后准备进行抓取。
抓取 excel 文件并获取 ID 号和姓名,将其放入列出的每个人的 for 循环中。
然后将每个人的 ID 号和姓名发送到我设置的 class,它将从网站上抓取 table。
class有5节,每个table有1节。每个 table 都有一个不同的 url,看起来像 {base_url}/{path_to_table}/{ID}(根据记忆简化)。
然后它告诉 webdriver 转到那个 URL,抓取它并将该数据发送到 docx-tpl。他们打开我拥有的 docx 模板文件,然后根据输入日期生成一个新文件。
那是loop/class的基础。问题是 URL 在 prod 和 dev 之间是不同的,登录是不同的(在 dev 中不存在)而且我确定还有一些我忘记的其他差异。
明天我看看能不能在网上发布一些代码,帮助你们看看我犯了多少错误:D
我认为您误解了 Python 模块的工作方式。我采用的方法是使用类似以下结构的脚本来实现:
base-dir/
setup.py <-- with entrypoints and dependencies defined
README.md
other_files.txt
main_module/
__init__.py <-- this marks it as a module
scrape.py <-- shared code
dev_specific.py
prod_specific.py
这样,如果您设置虚拟环境并使用 entrypoint 脚本,您将处于您指定的上下文中,并且可以正常导入和引用代码。您可以通过多种方式处理如何分离特定于环境的代码;最简单的是使用条件门,像这样:
if args.env == "production":
prod_specific.perform_login()
不同模块中定义的代码将不能访问调用模块中的代码或变量;您必须将任何相关信息作为参数传递给函数。不要将其视为被“拉入”另一个模块的包含代码;将其视为对该模块中代码可用的代码的 引用。
这可能是一个很长的问题,所以提前致歉。
这是我的情况,希望你们能帮我走上正轨:
塞纳里奥: 我有 2 个主要文件,我们称它们为 app-prod.py 和 app-dev.py。 两个(程序?)文件都使用 Selenium 来抓取网站,一个是主站点(工作),另一个是开发站点(本地)。 app-prod.py 需要一些登录代码(用户名、密码和授权代码)并且它必须告诉 Selenium 单击仅在生产站点上的某些按钮。
app-dev.py 不需要身份验证或导航说明,因为站点不同。开发站点只是一些模仿生产站点但没有所有登录内容的 html table。
生产代码示例:
# app-prod.py
"""open browser to base url, login and get ready
logic to login and go to the right page goes here"""
base_url = config[env]["base_url"]
browser = Firefox()
browser.get(base_url)
print("Sleeping for 5 to let page load")
time.sleep(5)
# LOGIN SCRIPT
auth = input("Enter Auth Code: ")
username = "LETMEIN"
password = "P@55W@rD"
browser.find_element_by_xpath('//*[@id="username"]').send_keys(username)
browser.find_element_by_xpath('//*[@id="password_input"]').send_keys(password)
browser.find_element_by_xpath('//*[@id="secondary_password_input"]').send_keys(auth)
browser.find_element_by_xpath('//input[@name="Login"]').click()
print("Sleeping for 3 to let page load")
time.sleep(3)
# Click OK button on alert
browser.find_element_by_xpath('//input[@value="Continue"]')
class Table:
def __init__(self, vls, name, intro):
**********
开发代码示例:
# app-dev.py
"""open browser to base url, login and get ready
logic to login and go to the right page goes here"""
base_url = config[env]["base_url"]
browser = Firefox()
browser.get(base_url)
class Table:
def __init__(self, vls, name, intro):
**********
我的问题是跟踪 2 个不同的文件。如果我处理开发代码,那么我必须将所有更改添加到 prod 文件,同时确保不要弄乱登录代码部分。 我目前正在使用 VS Code 比较这两个文件,然后 copy/paste 从开发到生产的差异,这是可行的,但有点乏味。
我尝试将代码的登录部分模块化并导入它,但它抱怨“浏览器”未定义(因为 webdriver 正在 app-*.py 文件中初始化)。
我以为当你导入一个模块时,它会把“import_me.py”中的所有东西都放到“app-dev.py”中,这样模块中的任何代码都可以使用任何主应用程序文件中的导入,但它似乎不是那样工作的。 就好像 python 在自己的小部分中将模块作为独立文件运行,而不与主文件交互。
所以,我的下一个想法是看看是否有一种模板应用程序的方法-dev.py 所以我可以说:
here is some dev code blah blah blah.
env='DEV'
if env == 'DEV'
{{ include login code here that is imported from import_me.py}}
else:
pass
不过好像没有这种东西。 每次我想测试某些东西时,我都无法一直访问生产站点,而且除了比较和手动进行更改之外,似乎没有一种干净的方法来处理两个不同的文件。
我正在使用 configparser 来更改 urls 和文件路径,但我认为它不能处理代码块,至少我没有在任何地方的文档中看到它。
你们是如何解决此类问题的?我编程的时间不长,所以我可能错过了一个可以解决这个问题的包,但现在,我没有想法。
非常感谢您能给我的任何帮助,希望能让我成为更好的程序员!
如果你做到了这一步,谢谢!有一个虚拟 cookie :)
TL;DR:需要一种方法将文件 1 中的代码块包含到文件 2 的特定区域中,文件 1 共享文件 2 的所有导入,就好像它是在运行时在那里硬编码一样。
**** 编辑以获取更多信息 **** 我会在明天查看有关发布代码的信息,因为我现在面前没有它。 这是我在做什么: 设置 Selenium 以打开网页,登录(在产品代码中),然后准备进行抓取。
抓取 excel 文件并获取 ID 号和姓名,将其放入列出的每个人的 for 循环中。 然后将每个人的 ID 号和姓名发送到我设置的 class,它将从网站上抓取 table。
class有5节,每个table有1节。每个 table 都有一个不同的 url,看起来像 {base_url}/{path_to_table}/{ID}(根据记忆简化)。 然后它告诉 webdriver 转到那个 URL,抓取它并将该数据发送到 docx-tpl。他们打开我拥有的 docx 模板文件,然后根据输入日期生成一个新文件。
那是loop/class的基础。问题是 URL 在 prod 和 dev 之间是不同的,登录是不同的(在 dev 中不存在)而且我确定还有一些我忘记的其他差异。
明天我看看能不能在网上发布一些代码,帮助你们看看我犯了多少错误:D
我认为您误解了 Python 模块的工作方式。我采用的方法是使用类似以下结构的脚本来实现:
base-dir/
setup.py <-- with entrypoints and dependencies defined
README.md
other_files.txt
main_module/
__init__.py <-- this marks it as a module
scrape.py <-- shared code
dev_specific.py
prod_specific.py
这样,如果您设置虚拟环境并使用 entrypoint 脚本,您将处于您指定的上下文中,并且可以正常导入和引用代码。您可以通过多种方式处理如何分离特定于环境的代码;最简单的是使用条件门,像这样:
if args.env == "production":
prod_specific.perform_login()
不同模块中定义的代码将不能访问调用模块中的代码或变量;您必须将任何相关信息作为参数传递给函数。不要将其视为被“拉入”另一个模块的包含代码;将其视为对该模块中代码可用的代码的 引用。