在不同目录中执行相同名称的python脚本

时间:2018-09-24 09:26:20

标签: python django python-import

我具有以下文件结构:

A:

| _ a.py

| _ b.py

B:

| _ a.py

| _ b.py

我想动态执行A / b.py或B / b.py。

我正在使用以下代码:

from importlib import import_module    
    path = '/home/username/test/' + module + '/'
    if path not in sys.path:
        sys.path.append(path)
    script = import_module('b', 'Script')
    myClass = getattr(script, 'Script')
    run = myClass()

这样做,如果我先运行B / b.py,然后运行A / b.py,它将执行B / b.py而不是A / b.py。

要运行的第一个脚本将在下一轮执行。

我需要帮助以确保仅运行我想要的目录中的文件。

2 个答案:

答案 0 :(得分:0)

我正在对您要在此处完成的工作进行一些假设。即使这不是您想要的,它仍然可以向您正确的方向:您有两个不同的子目录,分别是 A B 。这些脚本包含名称相同的脚本 a.py b.py 。根据某些条件,您的脚本应调用 A / a.py A / a.py ,然后那么可能是 B / b.py B / b.py

我将 A B 设置为实际的python模块,即在两个文件夹中创建一个 __ init __。py 文件。然后有一个主脚本,以某种方式确定要使用哪个模块。

# root_folder/master.py
import sys
import A
import B

master_script_name = sys.argv[0]

print("I'm the master script : " + str(master_script_name))


def choose_module_A_or_B(arg):
  if arg == "A":
    print(" You chose module A !")
    return A
  return B


module = choose_module_A_or_B("A")

module.b.print_locations()

然后

# root_folder/A/__init__.py
from A import b

# root_folder/A/b.py
import os
import sys

# how to obtain paths and script name:
folder = os.path.dirname(os.path.realpath(__file__))
script = __file__
parent = os.path.abspath(os.path.join(folder, os.pardir))

def print_locations():
  print(" --> script : " + str(script))
  print(" --> folder : " + str(folder))
  print(" --> parent : " + str(parent))

Similally ..

# root_folder/B/__init__.py
from B import b

# root_folder/B/b.py
import os
import sys

# how to obtain paths and script name:
folder = os.path.dirname(os.path.realpath(__file__))
script = __file__
parent = os.path.abspath(os.path.join(folder, os.pardir))

def print_locations():
  print(" --> script : " + str(script))
  print(" --> folder : " + str(folder))
  print(" --> parent : " + str(parent))

输出:

$ python master.py
I'm the master script : master.py
You chose module A !
--> script : A\b.py
--> folder : C:\dev\ScriptTesting\py\script_by_name\A
--> parent : C:\dev\ScriptTesting\py\script_by_name

答案 1 :(得分:0)

我已经阅读了您的其他类似question,并提出了没有任何预导入的解决方案。 (恕我直言)这是非常不符合Python的语言,因此绝对可以认为是肮脏的“ hack”。我强烈建议您考虑我的其他答案,并妥善处理进口问题。

发生您的问题是因为您要破坏名称空间,而所有名称空间都很宝贵。当您使用具有相同签名的函数/方法对名称空间进行污染时,Python解释器绝对无法区分它们:它将解析为首次导入的名称。

但是,如上所述,有一种解决方法:(当前)无法卸载 python模块,但是您可以使用reload imp模块。本质上,它使您可以清理(重新定义)名称空间。您可以在我的repl.it

中找到一个完整的有效示例
# root_folder/main.py
import sys
import imp
from importlib import import_module


def import_script(mod_dir, script):
  sys.path.append(mod_dir)
  mod = imp.reload(import_module(script, 'Script'))
  sys.path.remove(mod_dir)
  return mod

# input:
mod_dir = "A"
script = "b"

# import module/script.py
active_mod = import_script(mod_dir, script)

# use module/script.py
mod_name = active_mod.get_mod_name()
print(mod_name) # Prints "A : b.y"


# New input: different module/script.py
mod_dir = "C"
script = "b"

# import module/script.py
active_mod = import_script(mod_dir, script)

# use module/script.py
mod_name = active_mod.get_mod_name()
print(mod_name) # Prints "C : b.y"

当模块如下所示时,

# root_folder/A/b.py
def get_mod_name():
  return "A : b.py"

请注意,每次导入都会加倍,因为每次导入模块(名称可能重复)时,都必须重新加载模块以清理名称空间。仅del模块是不够的。