如何编写既支持Windows又支持Linux的Python代码



我有一些代码需要在Windows和Linux上做非常相似的事情。不幸的是,我需要几个特定于系统的功能(例如隐藏文件:Python跨平台隐藏文件(。为了可读性和可维护性,编写代码的最佳方式是什么?

目前,该代码使用许多if语句在不同的平台上表现不同。我考虑过的另一种方法是将代码拆分为两个独立的函数,一个用于Windows,另一个用于Linux,但这意味着要在两个地方更新代码的主要部分。

请注意,代码的主要部分比这部分要长得多,也要复杂得多。

组合方法(最大的可维护性,但有大量if语句(:

import os
def sort_out_files():
if is_linux:
do_linux_preparations()
else:
do_windows_preparations()
# Main part of the code:
for file in os.listdir(folder):
if is_correct_file(file):
if is_linux:
do_main_actions_for_linux()
else:
do_main_actions_for_windows()
if is_linux:
do_linux_tidying_up()
else:
do_windows_tidying_up()

单独的方法(需要更多的维护,但需要更少的if语句(:

import os
def sort_out_files_linux():
do_linux_preparations()
# Main part of the code:
for file in os.listdir(folder):
if is_correct_file(file):
do_main_actions_for_linux()
do_linux_tidying_up()

def sort_out_files_windows():
do_windows_preparations()
# Main part of the code:
for file in os.listdir(folder):
if is_correct_file(file):
do_main_actions_for_windows()
do_windows_tidying_up()
def sort_out_files():
if is_linux:
sort_out_files_linux():
else:
sort_out_files_windows()

do_preparations()do_tidying_up()功能包括复制文件、提取等。

is_correct_file()检查文件是否具有正确的名称和正确的时间戳。

do_main_actions()涉及分析、移动和隐藏文件。

上面的例子都有效,但似乎不是最Python的或长期代码可维护性的最佳方法。

我会把只适用于一个操作系统的所有东西放在一个文件中,但名称相同。然后你可以在主文件的开头添加这样的内容:

if is_linux:
import linux_tools as tools
else:
import windows_tools as tools

如果这两个文件具有相同的接口(例如,顶级方法(,则它们可以互换使用。

在您的示例中,linux_toolswindows_tools都包含各自的sort_out_files实现,但都命名为sort_out_files,因此可以将其与tools.sort_out_files一起使用。

请记住,在这些模块中尽可能多地保留通用代码。

为了使代码更易于维护,我建议研究适配器设计模式。

例如:您可以创建一个适配器类,而不是每次需要运行特定于操作系统的函数时都调用if语句。在运行时,您将使用适当的特定于操作系统的实现创建适配器,并在需要时引用它。

适配器设计示例:

# Adapter interface
class Adapter:
def SomeAction():
raise NotImplementedError
def SomeOtherAction():
raise NotImplementedError
# Windows implementation
class WindowsAdapter(Adapter):
def SomeAction():
print("Windows action!")
def SomeOtherAction():
print("Windows other action!")
# Linux implementation
class LinuxAdapter(Adapter):
def SomeAction():
print("Linux action!")
def SomeOtherAction():
print("Linux other action!")

为了避免代码中的重复条件,您可以在专用子模块中定义所有特定于平台的函数(每个平台一个子模块(,然后有条件地导入与主机匹配的函数

主文件

if is_linux:
import .fs_platform_windows as fs
else:
import .fs_platform_linux as fs
def sort_out_files():
fs.do_preparations()
# Main part of the code:
for file in os.listdir(folder):
if is_correct_file(file):
fs.do_main_actions()
fs.do_tidying_up()

显然,您需要让两个子模块实现相同的功能(使用相同的名称(。这是一种多态性,如果你想把所有的代码都放在同一个文件中,你可以用类得到相同的结果。

最新更新