import sys
import os
from subprocess import Popen, PIPE, STDOUT
# Transfer Database
print ('Transferring from ' + mysql_source_database)
mysql = Popen(f"mysql -h {mysql_dest_host} -P 3306 -u {mysql_dest_username} -p{mysql_dest_pw} {mysql_dest_database}".split(), stdin=PIPE, stdout=PIPE)
dbnamerewrite = Popen(f"sed s/{mysql_source_database}/{mysql_dest_database}/g".split(), stdin=PIPE, stdout=mysql.stdin)
mysqldump = Popen(f"mysqldump --set-gtid-purged=OFF --column-statistics=0 -h {mysql_source_host} -P 3306 -u {mysql_source_username} -p{mysql_source_pw} {mysql_source_database}".split(), stdout=dbnamerewrite.stdin)
mysql_stdout = mysql.communicate()[0]
mysqldump.wait()
上面的代码做了我想要的,但从未停止等待。有谁知道如何解决等待。如果我在 SQL 工作完成后按 ctrl-c,这是给定的错误:
^CERROR 1064 (42000) at line 3829: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3
Traceback (most recent call last):
File "test.py", line 19, in <module>
mysql_stdout = mysql.communicate()[0]
File "/usr/lib/python3.8/subprocess.py", line 1028, in communicate
stdout, stderr = self._communicate(input, endtime, timeout)
File "/usr/lib/python3.8/subprocess.py", line 1868, in _communicate
ready = selector.select(timeout)
File "/usr/lib/python3.8/selectors.py", line 415, in select
fd_event_list = self._selector.poll(timeout)
KeyboardInterrupt
答案 0 :(得分:3)
有一件事是您应该放弃对 import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
'https://boo.ua/catalog/smartfony/huawei-p30-lite-4-128gb--mar-lx1a-/',
'https://boo.ua/catalog/smartfony/huawei-p20-2018-4-128gb-black-eml-l29/',
]
def parse(self, response):
for quote in response.xpath('(descendant::div[@class="col-lg-5 model__spec"])'):
quote = quote.getall()
quote = [i.replace("\t", "").replace("\n", "") for i in quote]
yield {
'specification': quote
}
的显式调用。根据{{3}}:
注意:这将在使用 mysqldump.wait()
或 stdout=PIPE
时死锁,并且子进程向管道生成足够的输出,从而阻止等待操作系统管道缓冲区接受更多数据。使用管道时使用 docs 来避免这种情况。
Popen.communicate()
在这种情况下就足够了,因为在管道上的所有元素都发送一个 EOF 之前,它不会收到 EOF。所以stderr=PIPE
直接返回意味着其他两个进程都完成了。
另一个问题是,根据您拥有的进程的顺序,您必须以相反的顺序对所有进程调用 mysql.communicate()
才能使数据流过管道。一种解决方案就是这样做:
communicate
另一种选择是以相反的顺序设置管道,在这种情况下,您只需要db_param = ['-h', mysql_dest_host, '-P', '3306', '-u', mysql_dest_username, f'p{mysql_dest_pw}', mysql_dest_database]
mysql = Popen(['mysql'] + db_param,
stdin=PIPE, stdout=PIPE)
dbnamerewrite = Popen(['sed', f's/{mysql_source_database}/{mysql_dest_database}/g'],
stdin=PIPE, stdout=mysql.stdin)
mysqldump = Popen(['mysqldump', '--set-gtid-purged=OFF', '--column-statistics=0'] + db_param,
stdout=dbnamerewrite.stdin)
mysqldump.communicate()
dbnamerewrite.communicate()
mysql_stdout = mysql.communicate()[0]
执行最后一个过程:
communicate