如何在Python中调用一个脚本并同时运行另一个脚本?

alv*_*ini 1 python concurrency subprocess

我想要完成的是从 Twitter 传输一小时的推文,将推文列表写入文件,清理并运行最近一小时的推文分析,然后无限期地重复该过程。

我遇到的问题是,如果我在处理流的同一脚本中运行推文的清理和分析 - 通过对其进行硬编码或从模块导入功能 - 整个脚本将等待这些过程完成,然后再次开始流式传输。有没有办法在流脚本中调用清理和分析模块,以便它们同时运行,并且在清理和分析发生时流不会停止?

我尝试通过使用subprocess.call('python cleaner.py', shell=True)和来实现此subprocess.Popen('python cleaner.py', shell=True)目的,但我真的不知道如何正确使用这些工具,上面的两个示例导致流媒体停止、cleaner.py运行,然后恢复流媒体。

zvo*_*one 7

子流程

正如您尝试的那样,您可以使用subprocess.Popen来同时运行不同的脚本:

the_other_process = subprocess.Popen(['python', 'cleaner.py'])
Run Code Online (Sandbox Code Playgroud)

仅此一条线就可以满足您的要求。你不想做的是:

the_other_process.communicate()
# or
the_other_process.wait()
Run Code Online (Sandbox Code Playgroud)

这些将停止当前进程并等待另一个进程完成。在其他情况下这是一个非常有用的功能。

如果你想知道子进程是否完成(但不等待它):

result = the_other_process.poll()
if result is not None:
    print('the other process has finished and retuned %s' % result)
Run Code Online (Sandbox Code Playgroud)

线

并发也可以使用线程来实现。在这种情况下,您不会运行新进程,而只是将当前进程拆分为并发部分。尝试这个:

def function_to_be_executed_concurrently():
    for i in range(5):
        time.sleep(1)
        print('running in separate thread', i)

thread = threading.Thread(target=function_to_be_executed_concurrently)
thread.start()

for i in range(5):
    time.sleep(1)
    print('running in main thread', i)
Run Code Online (Sandbox Code Playgroud)

上面的代码应该产生running in separate thread和的混合输出running in main thread

线程与进程

  • 使用subprocess,您可以运行任何可以从 shell 独立运行的内容。它不一定是Python。
  • 使用threading,您可以在并发执行线程中运行任何函数。
  • 线程共享相同的内存,因此很容易在它们之间共享数据(尽管需要同步时会出现问题)。对于流程来说,共享数据可能会成为一个问题。如果必须共享大量数据,子进程可能会慢得多。
  • 启动新进程比运行线程更慢并且消耗更多资源
  • 由于线程在同一个进程中运行,因此它们共享绑定到同一个GIL,这意味着大多数事情将在同一个 CPU 核心上运行。如果需要加速非常慢的 CPU 消耗任务,那么在单独的进程中运行它们可能会更快。

多重处理

multiprocessingmodule 提供了与 类似的接口threading,但它运行子进程。当您需要充分利用所有 CPU 核心时,这非常有用。


** 请注意,subprocess.Popen(['python', 'cleaner.py'])与 是同一件事subprocess.Popen('python cleaner.py', shell=True),但前者更好地练习学习。

例如,如果路径中有空格,则会失败:

subprocess.Popen('python My Documents\\cleaner.py', shell=True)
Run Code Online (Sandbox Code Playgroud)

它失败了,因为它将My和解释Documents\cleaner.py为两个单独的参数。

另一方面,这将按预期工作:

subprocess.Popen(['python', 'My Documents\\cleaner.py'])
Run Code Online (Sandbox Code Playgroud)

它有效,因为参数是通过使用列表显式分隔的。

如果参数之一位于变量中,则后者尤其优越:

subprocess.Popen(['python', path_to_file])
Run Code Online (Sandbox Code Playgroud)