经常读取后,PyMySQL抛出'BrokenPipeError'(PyMySQL throws 'BrokenPipeError' after making frequent reads)
我写了一个脚本来帮助我使用数据库。 具体来说,我正在尝试使用磁盘上的文件,并将此工作的结果添加到我的数据库。 我复制了下面的代码,但删除了与我的数据库无关的大部分逻辑,试图保持这个问题的广泛和有用。
我使用代码对文件进行操作并将结果添加到数据库中,覆盖与我正在处理的文件具有相同标识符的任何文件。 后来,我修改了脚本以忽略已经添加到数据库中的文档,现在无论何时运行它我都会收到错误:
pymysql.err.OperationalError: (2006, "MySQL server has gone away (BrokenPipeError(32, 'Broken pipe'))")
似乎服务器拒绝了请求,可能是因为我写的代码很差? 我注意到错误总是发生在文件列表中的相同位置,不会改变。 如果我重新运行运行代码,用仅列出程序崩溃的文件的列表替换文件列表,它可以正常工作。 这让我觉得在发出一定数量的请求之后,数据库才刚刚结束。
我在OS X上使用Python 3和MySQL Community Edition版本14.14。
代码(剥离了与数据库无关的东西):
import pymysql # Stars for user-specific stuff connection = pymysql.connect(host='localhost', user='root', password='*******', db='*******', use_unicode=True, charset="utf8mb4", ) cursor = connection.cursor() f_arr = # An array of all of my data objects def convertF(file_): # General layout: Try to work with input and add it the result to DB. The work can raise an exception # If the record already exists in the DB, ignore it # Elif the work was already done and the result is on disk, put it on the database # Else do the work and put it on the database - this can raise exceptions # Except: Try another way to do the work, and put the result in the database. This can raise an error # Second (nested) except: Add the record to the database with indicator that the work failed # This worked before I added the initial check on whether or not the record already exists in the database. Now, for some reason, I get the error: # pymysql.err.OperationalError: (2006, "MySQL server has gone away (BrokenPipeError(32, 'Broken pipe'))") # I'm pretty sure that I have written code to work poorly with the database. I had hoped to finish this task quickly instead of efficiently. try: # Find record in DB, if text exists just ignore the record rc = cursor.execute("SELECT LENGTH(text) FROM table WHERE name = '{0}'".format(file_["name"])) length = cursor.fetchall()[0][0] # Gets the length if length != None and length > 4: pass elif ( "work already finished on disk" ): # get "result_text" from disk cmd = "UPDATE table SET text = %s, hascontent = 1 WHERE name = %s" cursor.execute(cmd, ( pymysql.escape_string(result_text), file_["name"] )) connection.commit() else: # do work to get result_text cmd = "UPDATE table SET text = %s, hascontent = 1 WHERE name = %s" cursor.execute(cmd, ( pymysql.escape_string(result_text), file_["name"] )) connection.commit() except: try: # Alternate method of work to get result_text cmd = "UPDATE table SET text = %s, hascontent = 1 WHERE name = %s" cursor.execute(cmd, ( pymysql.escape_string(result_text), file_["name"] )) connection.commit() except: # Since the job can't be done, tell the database cmd = "UPDATE table SET text = %s, hascontent = 0 WHERE name = %s" cursor.execute(cmd, ( "NO CONTENT", file_["name"]) ) connection.commit() for file in f_arr: convertF(file)
I have written a script to help me work with a database. Specifically, I am trying to work with files on disk and add the result of this work to my database. I have copied the code below, but removed most of the logic which isn't related to my database to try to keep this question broad and helpful.
I used the code to operate on the files and add the result to the database, overwriting any files with the same identifier as the one I was working on. Later, I modified the script to ignore documents which have already been added to the database, and now whenever I run it I get an error:
pymysql.err.OperationalError: (2006, "MySQL server has gone away (BrokenPipeError(32, 'Broken pipe'))")
It seems like the server is rejecting the requests, possibly because I have written my code poorly? I have noticed that the error always occurs at the same place in the list of files, which doesn't change. If I re-run run the code, replacing the file list with a list of only the file on which the program crashes, it works fine. This makes me think that after making a certain number of requests, the database just bottoms out.
I'm using Python 3 and MySQL Community Edition Version 14.14 on OS X.
Code (stripped of stuff that doesn't have to do with the database):
import pymysql # Stars for user-specific stuff connection = pymysql.connect(host='localhost', user='root', password='*******', db='*******', use_unicode=True, charset="utf8mb4", ) cursor = connection.cursor() f_arr = # An array of all of my data objects def convertF(file_): # General layout: Try to work with input and add it the result to DB. The work can raise an exception # If the record already exists in the DB, ignore it # Elif the work was already done and the result is on disk, put it on the database # Else do the work and put it on the database - this can raise exceptions # Except: Try another way to do the work, and put the result in the database. This can raise an error # Second (nested) except: Add the record to the database with indicator that the work failed # This worked before I added the initial check on whether or not the record already exists in the database. Now, for some reason, I get the error: # pymysql.err.OperationalError: (2006, "MySQL server has gone away (BrokenPipeError(32, 'Broken pipe'))") # I'm pretty sure that I have written code to work poorly with the database. I had hoped to finish this task quickly instead of efficiently. try: # Find record in DB, if text exists just ignore the record rc = cursor.execute("SELECT LENGTH(text) FROM table WHERE name = '{0}'".format(file_["name"])) length = cursor.fetchall()[0][0] # Gets the length if length != None and length > 4: pass elif ( "work already finished on disk" ): # get "result_text" from disk cmd = "UPDATE table SET text = %s, hascontent = 1 WHERE name = %s" cursor.execute(cmd, ( pymysql.escape_string(result_text), file_["name"] )) connection.commit() else: # do work to get result_text cmd = "UPDATE table SET text = %s, hascontent = 1 WHERE name = %s" cursor.execute(cmd, ( pymysql.escape_string(result_text), file_["name"] )) connection.commit() except: try: # Alternate method of work to get result_text cmd = "UPDATE table SET text = %s, hascontent = 1 WHERE name = %s" cursor.execute(cmd, ( pymysql.escape_string(result_text), file_["name"] )) connection.commit() except: # Since the job can't be done, tell the database cmd = "UPDATE table SET text = %s, hascontent = 0 WHERE name = %s" cursor.execute(cmd, ( "NO CONTENT", file_["name"]) ) connection.commit() for file in f_arr: convertF(file)
原文:https://stackoverflow.com/questions/41645823
最满意答案
确保已在config.php中设置会话,不要将会话保存路径保留为空
例
$config['sess_driver'] = 'files'; $config['sess_cookie_name'] = 'ci_session'; $config['sess_expiration'] = 7200; $config['sess_save_path'] = APPPATH . 'cache/session/'; $config['sess_match_ip'] = FALSE; $config['sess_time_to_update'] = 300; $config['sess_regenerate_destroy'] = FALSE;
确保会话文件夹权限0700
确保您获得正确的帖子数据
public function updateInt() { // You can autoload it in config/autoload.php saves loading every page $this->load->library('session'); $aInt = array('my_interval' => $this->input->post('_interval')); $this->session->set_userdata('post', $aInt); // Use `(` and `)` not `[]` $interval = $this->session->userdata('post'); return $interval; } public function getInt() { $interval = $this->updateInt(); // Test echo $interval['my_interval']; // print $interval and do some stuff !! }
Make sure you have set your sessions in your config.php do not leave the session save path null
Example
$config['sess_driver'] = 'files'; $config['sess_cookie_name'] = 'ci_session'; $config['sess_expiration'] = 7200; $config['sess_save_path'] = APPPATH . 'cache/session/'; $config['sess_match_ip'] = FALSE; $config['sess_time_to_update'] = 300; $config['sess_regenerate_destroy'] = FALSE;
Make sure session folder permission 0700
Make sure you are getting correct post data what your after
public function updateInt() { // You can autoload it in config/autoload.php saves loading every page $this->load->library('session'); $aInt = array('my_interval' => $this->input->post('_interval')); $this->session->set_userdata('post', $aInt); // Use `(` and `)` not `[]` $interval = $this->session->userdata('post'); return $interval; } public function getInt() { $interval = $this->updateInt(); // Test echo $interval['my_interval']; // print $interval and do some stuff !! }
相关问答
更多-
是的,CodeIgniter的内置会话类确实使用cookie,但是,即使PHP中的标准Sessions也需要cookie。 因此,无论您使用哪种路由,CodeIgniter会话或标准会话,如果用户未启用cookie,Sessions将无法正常工作。 CodeIgniter的Session类的优点是它可以自动加密数据以防止cookie被篡改,并允许您根据数据库对cookie进行身份验证。 Yes, the CodeIgniter's inbuilt session class does use cookies ...
-
CodeIgniter会话(CodeIgniter sessions)[2023-07-19]
CI的会议实际上是cookie。 加密,但仍然是cookie。 这就是为什么更喜欢在数据库中存储会话,因为你(应该)处理攻击中较不可达的目标,特别是如果你使用Active Records,它会自动逃避你的查询(这样就可以避免SQL注入)。 此外,与cookie相反,DB没有可用的有限内存量,因此您可以存储任何数量的数据,缓存操作,并将它们隐藏在前端。 我不确定为什么需要它,除了一些会话数据由CI 自动加密的事实。 因此,即使您没有使用加密库,也会对某些加密进行加密(例如,在保存会话ID时)。 正如Kai Q ... -
在会话中添加数据: - $newdata = array( 'username' => 'johndoe', 'email' => 'johndoe@some-site.com', 'logged_in' => TRUE ); $this->session->set_userdata($newdata); 从会话中检索数据: - $this->session->all_userdat ...
-
CodeIgniter:在DB中存储会话,如何知道会话来自哪个?(CodeIgniter: storing sessions in DB, how to know who session came from?)[2022-06-13]
CodeIgniter会将数据存储在您在配置文件中指定的表中。 默认情况下,它是ci_session 。 会话信息(例如可通过$_SESSION访问的内容)被序列化并保存在名为user_data的列中。 该字段无法告诉您会话是否已过期(或换句话说,有多少人在线)。 您可以做的是使用last_activity列,该列是该会话最后一次活动的时间戳。 您可以运行SQL查询,选择last_activity小于2分钟前的session_id计数。 SELECT COUNT(`session_id`) AS `acti ... -
为什么codeigniter会将其session数据存储在cookie中?(Why does codeigniter store its sessiondata in a cookie?)[2021-09-13]
那是关于用户的数据。 如果他们想改变它......那又怎么样? 我不明白它是如何“不安全”的。 您可以加密会话数据,或使用数据库进行会话数据完整性验证。 文档是你的朋友; 用它。 对于它的价值来说,似乎并不使用本地PHP会话。 文档声称这为开发人员提供了“更多的灵活性”,但考虑到该页面上列出的警告,我无法想象如何。 Well, it's data about the user. If they want to change it... so what? I don't see how it's "insec ... -
确保已在config.php中设置会话,不要将会话保存路径保留为空 例 $config['sess_driver'] = 'files'; $config['sess_cookie_name'] = 'ci_session'; $config['sess_expiration'] = 7200; $config['sess_save_path'] = APPPATH . 'cache/session/'; $config['sess_match_ip'] = FALSE; $config['sess_tim ...
-
你加载了会话库吗? $这个 - >负载>库( '会议'); 这可能是一个愚蠢的问题,但它并没有伤害问。 如何设置加密密钥? 我想你会看到一个错误消息http://ellislab.com/codeigniter/user_guide/libraries/encryption.html $session_data = array('uid' => 'test user', 'logged_in' => TRUE); $this->session->set_userdata($session_data); / ...
-
发现了一些问题。 第一。 在您的模型verify_user()方法中返回row() 此处的 CI文档显示row()返回具有第一个单个结果的对象。 第二。 在你的Nxlogin控制器index()方法中,你的row()被加载到$ res中,但是你引用的行[0]是不正确的。 引用您的结果,如$res->id和$res->email_address 第三。 你应该使用$this->load->library('session');初始化你的会话$this->load->library('session'); 在你 ...
-
codeigniter - 在会话中存储发布数据并在视图中显示(codeigniter - store post data in session and display in view)[2022-05-30]
您如何处理用户提交给表单的信息? 是不是保存到数据库或类似的? 如果是这样的话,为什么不从那里检索数据? 如果您只想暂时保存数据,可以像上一个示例中那样使用会话变量,但只需进行一些修改: function new_blank_order_lines() { $data = array( 'customer' =>$this->input->post('customer'), 'period' =>$this->input->post('period'), 'buom' ... -
不幸的是,php不允许您序列化对另一个对象的引用。 这就是为什么当您恢复对象时它不包含它开始的数据。 我提出的最佳解决方案是在我的模型层中创建一个使用cookie恢复的Session对象。 数据库中的会话表处理对您将序列化的对象的引用。 加载会话模型后,您可以使用它来热切地或懒洋洋地加载“会话存储”对象。 此外,如果这些对象持有对其他模型对象的引用,则可以使用相同的原则来遍历模型层的其余部分,具体取决于关系引用。 这看起来令人生畏,但如果您不自觉地实现它,可以查看一些ORM。 Unfortunately, ...